CompletionService

CompletionService将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者take已完成的任务,并按照完成这些任务的顺序处理它们的结果。例如,CompletionService 可以用来管理异步 IO ,执行读操作的任务作为程序或系统的一部分提交,然后,当完成读操作时,会在程序的不同部分执行其他操作,执行操作的顺序可能与所请求的顺序不同。

通常,CompletionService依赖于一个单独的Executor 来实际执行任务,在这种情况下,CompletionService只管理一个内部完成队列。ExecutorCompletionService类提供了此方法的一个实现。


Future poll()
获取并移除表示下一个已完成任务的 Future,如果不存在这样的任务,则返回 null。

Future poll(long timeout, TimeUnit unit)
获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则将等待指定的时间(如果有必要)。

Future submit(Callable task)
提交要执行的值返回任务,并返回表示挂起的任务结果的Future。

Future submit(Runnable task, V result)
提交要执行的 Runnable 任务,并返回一个表示任务完成的 Future,可以提取或轮询此任务。

Future take()
获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。


###示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.zero.test;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CompletionServiceTest {

public static void main(String[] args) {
// TODO Auto-generated method stub
CompletionService<String> completionService = new ExecutorCompletionService<String>(
Executors.newSingleThreadExecutor());
for (int i = 0; i < 3; i++) {
completionService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
for (int j = 0; j < 3; j++) {
System.out.println("calling----" + j);
TimeUnit.SECONDS.sleep(1);
}
return "hello!!!";
}
});
}
try {
for (int i = 0; i < 3; i++) {
Future<String> future = completionService.take();
System.out.println(future.get());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

CompletionService的实现是维护一个保存Future对象的BlockingQueue。只有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出 Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。先完成的必定先被取出,这样就减少了采用List来维护Future方式时不必要的等待时间。