之前的报价代码题目

  1. // 向电商S1询价,并保存
  2. r1 = getPriceByS1();
  3. save(r1);
  4. // 向电商S2询价,并保存
  5. r2 = getPriceByS2();
  6. save(r2);
  7. // 向电商S3询价,并保存
  8. r3 = getPriceByS3();
  9. save(r3);

优化后就是用三个Future来做,但是如果某一个查询报价很慢, 就会导致后面的save都无法执行。
为了优化这个 可以把查询报价的结果都保存到一个队列中,然后新开一个线程去消费队列,这样能保证获取到报价的任务都能保存到表里、
但是实现的代码很值得参考,直接把bq.put(f1.get())放到线程池的执行函数中,代码看起来很整齐。骚的一批。

  1. // 创建阻塞队列
  2. BlockingQueue<Integer> bq =
  3. new LinkedBlockingQueue<>();
  4. //电商S1报价异步进入阻塞队列
  5. executor.execute(()->
  6. bq.put(f1.get()));
  7. //电商S2报价异步进入阻塞队列
  8. executor.execute(()->
  9. bq.put(f2.get()));
  10. //电商S3报价异步进入阻塞队列
  11. executor.execute(()->
  12. bq.put(f3.get()));
  13. //异步保存所有报价
  14. for (int i=0; i<3; i++) {
  15. Integer r = bq.take();
  16. executor.execute(()->save(r));
  17. }

利用 CompletionService 实现 Dubbo 中的 Forking Cluster

就是并行的调用多个函数,只要有一个返回了结果就算完事,典型的应用场景就是调用多个地图的API,那个快用哪个,最大限度保证用户的体验,这优化很ojbk,欧力给,一给我滴giao giao ,互联网企业的确是考虑的多啊 赞。

  1. geocoder(addr) {
  2. //并行执行以下3个查询服务,
  3. r1=geocoderByS1(addr);
  4. r2=geocoderByS2(addr);
  5. r3=geocoderByS3(addr);
  6. //只要r1,r2,r3有一个返回
  7. //则返回
  8. return r1|r2|r3;
  9. }

CompletionService的优点

  1. CompletionService 将线程池 Executor 和阻塞队列 BlockingQueue 的功能融合在了一起,能够让批量异步任务的管理更简单
  2. CompletionService 能够让异步任务的执行结果有序化,先执行完的先进入阻塞队列


课后思考

返回最小的

解答

  1. 需要等待所有线程都执行完成后再来获取结果
  2. 如果米有save(),只有最小的嘛 就直接for循环遍历各个结果就可以了