Fork/Join框架學習筆記(三)
多線程
《Fork/Join框架學習筆記(一)》
《Fork/Join框架學習筆記(二)》
一些類
先說最重要的兩個:
ForkJoinPool池類
用來執行任務(ForkJoinTask),生成新的工作線程(ForkJoinWorkerThread)。
負責工作線程間的工作竊取。
線程池的個數一般是CPU核數。
執行任務有三個方法:
invoke:同步執行帶返回值的任務。ForkJoinTask.invoke。
submit:非同步執行帶返回值(Future)的任務。ForkJoinTask.fork(ForkJoinTasks are Futures)。
execute:非同步執行不帶返回值的任務。ForkJoinTask.fork。
(大家可以看前文的兩個例子)
ForkJoinTask任務類
ForkJoinTask就是用來執行的任務類,主要是工作是大任務的分割(Fork)以及結果的合併(Join),結合之前的例子可看,這是我們主要的編碼區。
不過真正工作中我們是不用這個類的,而是用它的兩個子類:
RecursiveAction,沒有返回值。
RecursiveTask,有返回值。
ForkJoinTask有幾個重要方法:
fork(),非同步執行當前Task。
invoke(),同步執行,等待任務完成並返回結果。
invokeAll(),同步執行給的Task,等待所有任務完成並返回結果。
join(),獲取返回值。不可中斷,否則會拋出InterruptedException。如果運行的任務拋出異常,返回RuntimeException。
get(),獲取返回值。如果運行的任務拋出異常,返回ExecutionException。
說說invokeAll(task1,task2)這個方法。具體代碼不再附上。其步驟是:
1、 執行task2的fork()。fork()代碼步驟不再附上,步驟如下:
1)先通過push ()將任務放入當前線程的工作隊列的Top位置。注意之前提到的「工作竊取」,放在Top位置可以優先讓本線程處理。
額外再說一句,有的資料上說用pushTask()。我看的是JDK8源碼,用push()。
2)如果隊列滿了,擴容。
3)如果隊列中的任務比較少(<=1),就執行ForkJoinPool.signalWork()方法,喚醒一個空閑的線程,或新建一個線程去立即執行。
由上可知,如果隊列中任務較多,Task就會存在workQueue中,可供其他工作線程進行「工作竊取」。
2、 task1調用doInvoke()方法,直接同步執行。先判斷任務狀態,如果狀態為<0(正常、取消、異常等),則說明任務執行完畢,返回狀態。否則就執行任務,然後判斷是否結束,如果結束就把狀態置為「正常」,否則就等待任務完成。
3、 task1執行完,task2調用doJoin()方法。join()方法也主要是調用doJoin(),其主要工作就是判斷任務的狀態,如果狀態為<0(正常、取消、異常等),則說明任務已經執行完畢,返回狀態。否則就通過tryUnpush()從隊尾(隊列的Top位置)取任務執行。
TAG:Java個人學習心得 |