CompletionService接口:
将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。例如,CompletionService 可以用来管理异步 IO ,执行读操作的任务作为程序或系统的一部分提交,然后,当完成读操作时,会在程序的不同部分执行其他操作,执行操作的顺序可能与所请求的顺序不同。
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;
/**
* 演示CompletionService的使用
*
* @author Administrator
*
*/
public class CompletionServiceTest {
private static final ExecutorService exec = Executors
.newFixedThreadPool(10);
public static void main(String[] args) throws InterruptedException,
ExecutionException {
CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(
exec);
final int nums[] = { 1 };
for (int i = 0; i < 5; i++) {//提交五个任务
cs.submit(new Callable<Integer>() {
public Integer call() throws Exception {
Thread.sleep(nums[0] * 1000);
++nums[0];
return nums[0];
}
});
// System.out.println(nums[0]);
}
for (int i = 0; i < 5; i++) {//得到五个任务
Future<Integer> f = cs.take();
System.out.println(f.get());
}
exec.shutdown();
}
}
运行程序却发现会有如下结果:
2
2
3
5
4
上边是一次运行结果,也就说不同的任务返回了相同的值。分析原因,是由++nums[0];的非原子性导致的。
将其加锁,把提交任务的部分改为:
for (int i = 0; i < 5; i++) {//提交五个任务
cs.submit(new Callable<Integer>() {
public Integer call() throws Exception {
Thread.sleep(nums[0] * 1000);
synchronized(nums){
++nums[0];
}
return nums[0];
}
});
// System.out.println(nums[0]);
}
运行结果:
2
3
4
5
6
。问题解决