2011-10-13 74 views

回答

19

假设你有一组任务A, B, C, D, E的几个例子,你想在Executor异步执行它们各自和处理结果1 1,因为他们完成。

随着Executor,你会做这样这样的:

List<Future<?>> futures = new ArrayList<Future<?>>(); 
futures.add(executorService.submit(A)); 
futures.add(executorService.submit(B)); 
futures.add(executorService.submit(C)); 
futures.add(executorService.submit(D)); 
futures.add(executorService.submit(E)); 

//This loop must process the tasks in the order they were submitted: A, B, C, D, E 
for (Future<?> future:futures) { 
    ? result = future.get(); 
    // Some processing here 
} 

这种方法的问题是,有没有保证,任务A将首先完成。因此,当主线程可能正在处理另一个任务(例如任务B)的结果时,主线程可能会空闲阻塞等待任务A完成。通过使用ExecutorCompletionService可以减少结果处理等待时间。

List<Future<?>> futures = new ArrayList<Future<?>>(); 
futures.add(executorCompletionService.submit(A)); 
futures.add(executorCompletionService.submit(B)); 
futures.add(executorCompletionService.submit(C)); 
futures.add(executorCompletionService.submit(D)); 
futures.add(executorCompletionService.submit(E)); 

//This for loop will process the tasks in the order they are completed, 
//regardless of submission order 
for (int i=0; i<futures.size(); i++) { 
    ? result = executorCompletionService.take().get(); 
    // Some processing here 
} 

因此,在本质上,ExecutorCompletionService可用于挤出多一点效率时的处理任务结果的顺序并不重要。

但要注意的一点很重要。 ExecutorCompletionService的实现包含一个结果队列。如果不调用takepoll来排空该队列,则会发生内存泄漏。有些人使用submit返回的Future来处理结果,这是不正确的用法。

+0

正确的用法只是为了自己创造未来;) – bestsss

+1

非常感谢Tim的支持。这个例子和解释很清楚。 –

+0

这样一个惊人的答案,到目前为止只有18票。这让我难过。那个婴儿看起来很可爱在你的手中。 –