之前的报价代码题目
// 向电商S1询价,并保存
r1 = getPriceByS1();
save(r1);
// 向电商S2询价,并保存
r2 = getPriceByS2();
save(r2);
// 向电商S3询价,并保存
r3 = getPriceByS3();
save(r3);
优化后就是用三个Future来做,但是如果某一个查询报价很慢, 就会导致后面的save都无法执行。
为了优化这个 可以把查询报价的结果都保存到一个队列中,然后新开一个线程去消费队列,这样能保证获取到报价的任务都能保存到表里、
但是实现的代码很值得参考,直接把bq.put(f1.get())放到线程池的执行函数中,代码看起来很整齐。骚的一批。
// 创建阻塞队列
BlockingQueue<Integer> bq =
new LinkedBlockingQueue<>();
//电商S1报价异步进入阻塞队列
executor.execute(()->
bq.put(f1.get()));
//电商S2报价异步进入阻塞队列
executor.execute(()->
bq.put(f2.get()));
//电商S3报价异步进入阻塞队列
executor.execute(()->
bq.put(f3.get()));
//异步保存所有报价
for (int i=0; i<3; i++) {
Integer r = bq.take();
executor.execute(()->save(r));
}
利用 CompletionService 实现 Dubbo 中的 Forking Cluster
就是并行的调用多个函数,只要有一个返回了结果就算完事,典型的应用场景就是调用多个地图的API,那个快用哪个,最大限度保证用户的体验,这优化很ojbk,欧力给,一给我滴giao giao ,互联网企业的确是考虑的多啊 赞。
geocoder(addr) {
//并行执行以下3个查询服务,
r1=geocoderByS1(addr);
r2=geocoderByS2(addr);
r3=geocoderByS3(addr);
//只要r1,r2,r3有一个返回
//则返回
return r1|r2|r3;
}
CompletionService的优点
- CompletionService 将线程池 Executor 和阻塞队列 BlockingQueue 的功能融合在了一起,能够让批量异步任务的管理更简单
- CompletionService 能够让异步任务的执行结果有序化,先执行完的先进入阻塞队列
课后思考
解答
- 需要等待所有线程都执行完成后再来获取结果
- 如果米有save(),只有最小的嘛 就直接for循环遍历各个结果就可以了