English 中文(简体)
Understanding future/threading
原标题:

I am trying to use futures for the first time. It seems smart that you can cancel a job, but it is not working as expected. In the example below, only the first job is cancelled. The rest are completed. Have I misunderstood the use of futures?

public class ThreadExample 
{
    public static void main(String[] args) throws InterruptedException, ExecutionException 
    {
        int processors = Runtime.getRuntime().availableProcessors();
        System.out.println("Processors: " + processors);
        ExecutorService es = Executors.newFixedThreadPool(processors);
        int nowork = 10;
        Future<Integer>[] workres = new Future[nowork];
        for(int i = 0; i < nowork; i++)
        {
            workres[i] = es.submit(new SomeWork(i));
        }
        for(int i = 0; i < nowork; i++) 
        {
            if(i % 2 == 0)
            {
                System.out.println("Cancel");
                workres[i].cancel(true);
            }
            if(workres[i].isCancelled())
            {
                System.out.println(workres[i] + " is cancelled");
            }
            else
            {
                System.out.println(workres[i].get());
            }
        }
        es.shutdown();
    }
}

class SomeWork implements Callable<Integer> 
{
    private int v;
    public SomeWork(int v) 
    {
        this.v = v;
    }

    @Override
    public Integer call() throws Exception
    {
        TimeUnit.SECONDS.sleep(5);
        System.out.println(v + " done at " + (new Date()));
        return v;
    }
}

The output:

Processors: 4
Cancel
java.util.concurrent.FutureTask@10d448 is cancelled
4 done at Wed May 12 17:47:05 CEST 2010
2 done at Wed May 12 17:47:05 CEST 2010
1 done at Wed May 12 17:47:05 CEST 2010
3 done at Wed May 12 17:47:05 CEST 2010
1
Cancel
2  
3
Cancel
4
5 done at Wed May 12 17:47:10 CEST 2010
7 done at Wed May 12 17:47:10 CEST 2010
8 done at Wed May 12 17:47:10 CEST 2010
6 done at Wed May 12 17:47:10 CEST 2010  
5
Cancel
6
7
Cancel
8
9 done at Wed May 12 17:47:15 CEST 2010  
9
最佳回答

The problem is that your cancellation loop is overlapping with your get() loop, which blocks. I think you want to have 2 loops, don t you? One loop that cancels even numbered jobs, and then a second loop that checks which ones are cancelled and which ones aren t, and then get() accordingly.

The way it s written right now, before the loop even had a chance to cancel workres[2], it checked and asked for get() from workres[1].

So I think you need 3 phases:

1. The `submit()` loop
2. The selective `cancel()` loop
3. The selective `get()` loop (which blocks)
问题回答

The Future#cancel() will not terminate/interrupt the already running jobs. It will only cancel the not-yet-running jobs.

Update: polygenelubricants nailed the root cause down (+1): here is the improved code:

int processors = Runtime.getRuntime().availableProcessors();
System.out.println("Processors: " + processors);
ExecutorService es = Executors.newFixedThreadPool(processors);
int nowork = 10;
Future<Integer>[] workers = new Future[nowork];

for (int i = 0; i < nowork; i++) {
    final int ii = i;
    workers[i] = es.submit(new Callable<Integer>() {
        public Integer call() throws Exception {
            return ii;
        }
    });
}

for (int i = 0; i < nowork; i++) {
    if (i % 2 == 0) {
        System.out.println("Cancel worker " + i);
        workers[i].cancel(true);
    }
}

for (int i = 0; i < nowork; i++) {
    if (workers[i].isCancelled()) {
        System.out.println("Worker " + i + " is cancelled");
    } else {
        System.out.println("Worker " + i + " returned: " + workers[i].get());
    }
}

es.shutdown();

Result:

Processors: 2
Cancel worker 0
Cancel worker 2
Cancel worker 4
Cancel worker 6
Cancel worker 8
Worker 0 is cancelled
Worker 1 returned: 1
Worker 2 is cancelled
Worker 3 returned: 3
Worker 4 is cancelled
Worker 5 returned: 5
Worker 6 is cancelled
Worker 7 returned: 7
Worker 8 is cancelled
Worker 9 returned: 9

(note that it s workers, not workres).





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签