(1)作用
当使用ExecutorService启动了多个Callable之后,每个Callable会产生一个Future,通常我们需要将多个Future存入一个线性表中,用于之后的数据处理
CompletionService就是为此存在。它自身带有一个线程安全的线性表,无需用户创建。
(2)使用
1.非阻塞获取poll
如果当前没有结果,返回null,主线程继续运行2.阻塞获取take
如果当前没有结果,这主线程一直阻塞,直到返回结果 3.实例
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class CompletionServiceTest {
public static void main(String[] args) throws InterruptedException{
ExecutorService executor = Executors.newCachedThreadPool();
CompletionService<Integer> comp = new ExecutorCompletionService<Integer>(executor);
for(int i = 0; i<5; i++) {
comp.submit(new Task());
}
executor.shutdown();
int count = 0, index = 1;
while(count<5) {
Future<Integer> f = comp.poll();
if(f == null) {
System.out.println(index + " 没发现有完成的任务");
}else {
try {
System.out.println(index + "产生了一个随机数: " + f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
count++;
}
index++;
TimeUnit.MILLISECONDS.sleep(500);
}
}
}
class Task implements Callable<Integer> {
public Integer call() throws Exception {
Random rand = new Random();
TimeUnit.SECONDS.sleep(rand.nextInt(7));
if(!rand.nextBoolean())
throw new RuntimeException("test exception");
return rand.nextInt();
}
}