天天看點

并發工具類:CompletionService有什麼用?

并發工具類:CompletionService有什麼用?

如何優化任務執行?

開發了一個比價網站,當使用者查詢某個商品的價格時,從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種使用場景

并發工具類:CompletionService有什麼用?

同時調用多個相同的服務擷取結果,當有其中一個服務擷取到結果後就傳回,并取消其他任務。類似Dubbo的Forking Cluster

參考部落格