ForkJoinPool調用shutdown從而終止整個併發執行框架。
包括取消所有隊列中已有的任務,終止所有的工作線程。
考慮這樣一個場景,一個線程正在提交任務,另一個線程正在調用shutdown終止線程池。
此時涉及到3個獨立的執行邏輯:
- 調用pool.submit的線程
- 調用pool.shutdown()的線程
- 線程池中的工作線程
package com.psly;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class TestForkJoin {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ForkJoinPool pool = new ForkJoinPool();
new Thread(){
public void run(){
ForkJoinTask<String> task = pool.submit(new Callable<String>(){
public String call(){
return "Hello,world";
}
});
//輸出 Hello,world (永遠不會輸出,也不會報異常, 所以這是個bug)
try {
System.out.println(task.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
{ this.setName("printHelloWorld");this.start(); }
};
// Thread.sleep(1000);
new Thread(){
public void run(){
pool.shutdown();
}
{ this.setName("shutdownPool");this.start(); }
};
}
}
執行以上代碼,輸出爲:Exception in thread "printHelloWorld" java.util.concurrent.RejectedExecutionException
at java.util.concurrent.ForkJoinPool.externalSubmit(ForkJoinPool.java:2328)
at java.util.concurrent.ForkJoinPool.externalPush(ForkJoinPool.java:2419)
at java.util.concurrent.ForkJoinPool.submit(ForkJoinPool.java:2675)
at com.psly.TestForkJoin$1.run(TestForkJoin.java:14)
任務被拒絕,這是一個可接受的結果。// Thread.sleep(1000);
我們去除這一句註釋,讓shutdown線程晚1秒一點執行。Hello,world
這同樣是一個可以接受的結果。2359 U.putOrderedObject(a, j, task);
2224 rs = lockRunState(); // enter SHUTDOWN phase
然後再次註釋Thread.sleep(1000)。
// Thread.sleep(1000);
debug我們一開始給出的test case。
jdk9中的實現與8已經不一樣了。詳情可見點擊打開鏈接