Java 併發編程 Future及CompletionService

Future

Future用於異步結果計算。它提供了一些方法來檢查計算是否完成,使用get方法將阻塞線程直到結果返回

  • cancel:嘗試取消任務的執行,如果任務已完成或已取消,此操作無效
  • isCancelled:任務是否已取消
  • isDone:任務是否已完成
  • get:阻塞線程以獲取計算結果,直至任務執行完畢返回結果
  • get(long timeout, TimeUnit unit):阻塞線程以獲取計算結果,若在指定時間沒返回結果,則返回null
public  interface  Future<V> {
    boolean cancel(boolean  mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Future結合線程池的使用

public void futureTest(){
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    Future<String> nickFuture = executorService.submit(() -> userService.getNick());
    Future<String> nameFuture = executorService.submit(() -> userService.getUserName());

    // 阻塞開始,等待結果
    String nick = nickFuture.get(1000, TimeUnit.MILLISECONDS);
    String name = nameFuture.get();
}

CompletionService

CompletionService整合了ExecutorBlockingQueue的功能。將Callable任務提交給它去執行,使用take()poll()獲取最新完成的任務執行結果.

ExecutorCompletionService是該接口的實現類,內部有一個線程池和BlockingQueue隊列。它的實現原理其實挺簡單:每個提交給ExecutorCompletionService的任務,都會被封裝成一個QueueingFutureFutureTask的子類),它重寫了done()方法(該方法會在任務執行完成之後回調),將執行完成的FutureTask加入到內部隊列,take()poll()將得到最新完成的結果FutrueTask

使用方法

注:若線程池爲局部變量,使用完後需關閉線程池。或直接使用全局變量命名的線程池

public Map<Long, List<String>> batchDoGetLiveRecord(List<LiveRecordReqDTO> reqList) {
	Map<Long, List<String>> recordMap = Maps.newHashMap();
	// 用線程池executor新建一個CompletionService
	CompletionService<Map<Long, List<String>>> completionService = new ExecutorCompletionService<>(executor);

	try {
		for (LiveRecordReqDTO req : reqList) {
			completionService.submit(() -> doGetLiveRecordAsMap(req));
		}

		for (int i = 0; i < reqList.size(); i++){
			Map<Long, List<String>> map = completionService.take().get(1000, TimeUnit.MILLISECONDS);
			recordMap.putAll(map);
		}
	} catch (Exception e) {
		logger.warn("batchDoGetLiveRecord fail, uidList:{}, bizId:{}",reqList, bizId, e);
	} finally {
		completionService.shutdown();
	}

	return recordMap;
}

類圖自CompletionService和ExecutorCompletionService詳解
類圖自CompletionService和ExecutorCompletionService詳解


參考資料:

  1. CompletionService和ExecutorCompletionService詳解
  2. 併發處理利器-CompletionService
發佈了109 篇原創文章 · 獲贊 97 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章