并发工具类:CompletionService有什么用?
原创
©著作权归作者所有:来自51CTO博客作者wx6289ced28e34b的原创作品,请联系作者获取转载授权,否则将追究法律责任
如何优化任务执行?
开发了一个比价网站,当用户查询某个商品的价格时,从S1和S2两个平台获取到对应的价格,保存在数据库中后,返回给用户
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> f1 = executor.submit(()-> getPriceByS1());
Future<Integer> f2 = executor.submit(()-> getPriceByS2());
Integer price1 = f1.get();
save(price1);
Integer price2 = f2.get();
save(price2);
如果获取电商S1报价的耗时很长,即使获取电商S2报价的耗时很短,也无法让保存S2报价的操作先执行,因为主线程都阻塞在f1.get()操作上了
解决方案一:
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> f1 = executor.submit(()-> getPriceByS1());
Future<Integer> f2 = executor.submit(()-> getPriceByS2());
BlockingQueue<Integer> bq = new LinkedBlockingQueue<>();
bq.put(f1.get());
bq.put(f2.get());
for (int i = 0; i < bq.size(); i++) {
Integer price = bq.take();
save(price);
}
解决方案二:
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletionService<Integer> cs = new ExecutorCompletionService<>(executor);
cs.submit(() -> getPriceByS1());
cs.submit(() -> getPriceByS2());
for (int i = 0; i < 2; i++) {
Integer price = cs.take().get();
save(price);
}
那么CompletionService如何实现这个功能的呢?
是不是也是通过把BlockingQueue和Executor组合一下来达到类似的功能的
CompletionService的使用场景
在CompletionService类的注释上其实标标明了CompletionService的2种使用场景
同时调用多个相同的服务获取结果,当有其中一个服务获取到结果后就返回,并取消其他任务。类似Dubbo的Forking Cluster
参考博客
[1]Java并发小册