ThreadPool執行緒池使用及解決主執行緒和子執行緒執行順序問題
執行緒池建立五個執行緒,每個執行緒往list中新增100個元素。synchronized只鎖執行緒共享變數list物件,程式碼段內僅新增元素及列印資訊。設定10ms睡眠時間給其餘執行緒機會。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); //list是所有執行緒共享變數需要加鎖避免衝突 final List list = new ArrayList(); for(int i=0;i<5;i++) { fixedThreadPool.execute(new Runnable() { @Override public void run() { //j是執行緒內部變數,每個執行緒都有一份,自己會管理,不會衝突 int j=100; while(j>0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (list) { list.add(j); System.out.println(Thread.currentThread().getName()+"---------"+list.size()); j--; } } } }); } fixedThreadPool.shutdown(); //這裡的sysout輸出是在main執行緒中的,其list的size根據當時這個list的情況只輸出一次,可能是任意小於500的值 System.out.println(Thread.currentThread().getName()+"---------"+list.size());
輸出結果:(注意這裡的main-----0 這個值是fixedThreadPool.shutdown();之後的sysout輸出。)包括main執行緒一共有6個執行緒。
main執行緒不執行run內程式碼段,直接往下繼續執行其餘程式碼(如果快的話可能一行執行緒內程式碼都沒執行就執行run外的程式碼了)。
main---------0 pool-1-thread-2---------1 pool-1-thread-3---------2 pool-1-thread-4---------3
....
pool-1-thread-3---------497 pool-1-thread-2---------498 pool-1-thread-4---------499 pool-1-thread-5---------500
關於main執行緒:main執行緒可能在其餘子執行緒執行完就執行到尾了。但是很多生產情況是要獲取子執行緒結果來處理的。此時可以設定等待時間等待子執行緒結束。
-
// 啟動一次順序關閉,執行以前提交的任務,但不接受新任務。
-
threadPool.shutdown();
-
//// 設定最長等待5秒
-
if(!pool.awaitTermination(5, TimeUnit.SECONDS)){
-
// 超時的時候向執行緒池中所有的執行緒發出中斷(interrupted)。再超時直接強行關閉。
-
pool.shutdownNow();
-
}
或者可以用join()方法
-
// 使用執行緒安全的Vector
-
Vector<Thread> threads = new Vector<Thread>();
-
for (int i = 0; i < 10; i++) { ....... 省略建立子執行緒方法
-
threads.add(iThread); // 將每一個子執行緒放到集合中,iThread代表某個子執行緒
-
}
-
for (Thread iThread : threads) { //在主執行緒中迴圈呼叫子執行緒的join()
-
try {
-
// 等待所有執行緒執行完畢
-
iThread.join();
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
}
- System.out.println("主線執行。"); //這個sysout會在所有子執行緒完成後執行
關於shutdown:“問題解答完畢後請舉手示意!”是shutdown方法。“老師我做完了!”是各個任務(Runnable)的執行結束。
shutdown只作為通知的作用