我們知道,當不使用線程池時,想讓A線程在B線程執行完之後執行,需要在A中的某個調用處,調用B.join,但如果使用jdk1.5以後提供的線程池ExecutorService,這個就用不上了,用了會出同步問題,其實這個場景應該是很常見的吧,比如你用多線程併發執行一些操作,當這些操作全部完成時才能進行下一步,這就是需要這個功能了。後來偶然在網上看到有人說用ExecutorService.invokeAll可以實現,測試了一下,確實簡單。這個方法的定義如下:
你需要傳一個Callable實現類元素的集合給此方法,每個元素就是一個線程了,返回值是線程執行結果的集合,聲明的異常,按照文檔的說法---if interrupted while waiting, in which case unfinished tasks are cancelled,如果執行時出現了中斷異常,其它未執行完的線程會取消,但我經過測試,發現並沒有取消,仍舊正常執行了。下面給出個小例子:
邏輯極其簡單,啓動200個線程,每個線程先生成一個隨機數,如果大於5就拋出異常,中止,否則,睡10秒鐘,再輸出自己的名字。如果輸出結果是200條,說明不管有沒有線程拋出異常,其它異常仍舊會照常執行,使用完畢後一定要記得shutdown線程池,否則程序一直掛在那兒無法終止。運行結果,done總是在最後一行輸出,說明它總是等池裏的所有線程執行完後纔會執行到這一步,這樣你就可以把第二步的邏輯寫到這裏就行了。解決了很大的問題。