天天看點

java并發程式設計學習:如何等待多個線程執行完成後再繼續後續處理(synchronized、join、FutureTask、CyclicBarrier)

多線程應用中,經常會遇到這種場景:後面的處理,依賴前面的N個線程的處理結果,必須等前面的線程執行完畢後,後面的代碼才允許執行。

在我不知道CyclicBarrier之前,最容易想到的就是放置一個公用的static變量,假如有10個線程,每個線程處理完上去累加下結果,然後後面用一個死循環(或類似線程阻塞的方法),去數這個結果,達到10個,說明大家都爽完了,可以進行後續的事情了,這個想法雖然土鼈,但是基本上跟語言無關,幾乎所有主流程式設計語言都支援。

輸出結果:

thread 0 done

thread 0 => 1

thread 9 done

thread 9 => 2

thread 1 done

thread 1 => 3

thread 3 done

thread 3 => 4

thread 7 done

thread 7 => 5

thread 6 done

thread 6 => 6

thread 2 done

thread 2 => 7

thread 4 done

thread 4 => 8

thread 8 done

thread 8 => 9

thread 5 done

thread 5 => 10

-----------

所有thread執行完成!

除了這個方法,還可以借助FutureTask,達到類似的效果,其get方法會阻塞線程,等到該異步處理完成。缺點就是,FutureTask調用的是Callable,必須要有傳回值,是以就算你不想要傳回值,也得傳回點啥

執行結果:

task0 done

task1 done

task2 done

task3 done

task4 done

task5 done

task6 done

task7 done

task8 done

task9 done

所有task執行完成!

  

此外,Thread的Join方法也可以實作類似的效果,主要代碼如下:

當然,這個需求最“正統”的解法應該是使用CyclicBarrier,它可以設定一個所謂的“屏障點”(或稱集合點),好比在一項團隊活動中,每個人都是一個線程,但是規定某一項任務開始前,所有人必須先到達集合點,集合完成後,才能繼續後面的任務。  

thread 9 done,正在等候其它線程完成...

thread 5 done,正在等候其它線程完成...

thread 0 done,正在等候其它線程完成...

thread 6 done,正在等候其它線程完成...

thread 4 done,正在等候其它線程完成...

thread 2 done,正在等候其它線程完成...

thread 3 done,正在等候其它線程完成...

thread 8 done,正在等候其它線程完成...

thread 7 done,正在等候其它線程完成...

thread 1 done,正在等候其它線程完成...

參考文章:

<a href="http://ifeve.com/concurrency-cyclicbarrier/" target="_blank">http://ifeve.com/concurrency-cyclicbarrier/</a>

<a href="http://ifeve.com/thread-synchronization-utilities-5/" target="_blank">http://ifeve.com/thread-synchronization-utilities-5/</a>

<a href="http://ifeve.com/thread-management-7/" target="_blank">http://ifeve.com/thread-management-7/</a>