Java多執行緒4-初識執行緒池
前言
Java為什麼引入執行緒池?
建立執行緒示例
new Thread(new Runnable() { @Override public void run() { } }).start();
new Thread的弊端
- 每次new Thread新建物件效能差。
- 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
- 缺乏更多功能,如定時執行、定期執行、執行緒中斷。
相比new Thread,Java提供的四種執行緒池的好處在於:
- 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
- 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
- 提供定時執行、定期執行、單執行緒、併發數控制等功能。
1.Java四種執行緒池
Java通過Executors提供四種執行緒池,分別為:
newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。
1.1 newFixedThreadPool
建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
public class ThreadPoolTest { public static void main(String[] args) { //固定執行緒池 ExecutorService threadPool = Executors.newFixedThreadPool(3); for (int i = 1; i < 10; i++) { int finalI = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j < 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + finalI ); } } }); } } }
pool-1-thread-3 is looping of 1 for task of 3 pool-1-thread-2 is looping of 1 for task of 2 pool-1-thread-1 is looping of 1 for task of 1 pool-1-thread-3 is looping of 2 for task of 3 pool-1-thread-1 is looping of 2 for task of 1 pool-1-thread-2 is looping of 2 for task of 2 pool-1-thread-3 is looping of 3 for task of 3 pool-1-thread-1 is looping of 3 for task of 1 pool-1-thread-2 is looping of 3 for task of 2 pool-1-thread-3 is looping of 4 for task of 3 pool-1-thread-2 is looping of 4 for task of 2 pool-1-thread-1 is looping of 4 for task of 1 pool-1-thread-1 is looping of 5 for task of 1 pool-1-thread-2 is looping of 5 for task of 2 pool-1-thread-3 is looping of 5 for task of 3 pool-1-thread-1 is looping of 6 for task of 1 pool-1-thread-3 is looping of 6 for task of 3 pool-1-thread-2 is looping of 6 for task of 2 pool-1-thread-1 is looping of 7 for task of 1 pool-1-thread-3 is looping of 7 for task of 3 pool-1-thread-2 is looping of 7 for task of 2 pool-1-thread-1 is looping of 8 for task of 1 pool-1-thread-3 is looping of 8 for task of 3 pool-1-thread-2 is looping of 8 for task of 2 pool-1-thread-1 is looping of 9 for task of 1 pool-1-thread-2 is looping of 9 for task of 2 pool-1-thread-3 is looping of 9 for task of 3 pool-1-thread-1 is looping of 1 for task of 4 pool-1-thread-2 is looping of 1 for task of 5 pool-1-thread-3 is looping of 1 for task of 6 pool-1-thread-1 is looping of 2 for task of 4 pool-1-thread-2 is looping of 2 for task of 5 pool-1-thread-3 is looping of 2 for task of 6 pool-1-thread-1 is looping of 3 for task of 4 pool-1-thread-2 is looping of 3 for task of 5 pool-1-thread-3 is looping of 3 for task of 6 pool-1-thread-3 is looping of 4 for task of 6 pool-1-thread-1 is looping of 4 for task of 4 pool-1-thread-2 is looping of 4 for task of 5 pool-1-thread-3 is looping of 5 for task of 6 pool-1-thread-1 is looping of 5 for task of 4 pool-1-thread-2 is looping of 5 for task of 5 pool-1-thread-2 is looping of 6 for task of 5 pool-1-thread-1 is looping of 6 for task of 4 pool-1-thread-3 is looping of 6 for task of 6 pool-1-thread-2 is looping of 7 for task of 5 pool-1-thread-3 is looping of 7 for task of 6 pool-1-thread-1 is looping of 7 for task of 4 pool-1-thread-1 is looping of 8 for task of 4 pool-1-thread-3 is looping of 8 for task of 6 pool-1-thread-2 is looping of 8 for task of 5 pool-1-thread-3 is looping of 9 for task of 6 pool-1-thread-2 is looping of 9 for task of 5 pool-1-thread-1 is looping of 9 for task of 4 pool-1-thread-2 is looping of 1 for task of 8 pool-1-thread-1 is looping of 1 for task of 9 pool-1-thread-3 is looping of 1 for task of 7 pool-1-thread-1 is looping of 2 for task of 9 pool-1-thread-2 is looping of 2 for task of 8 pool-1-thread-3 is looping of 2 for task of 7 pool-1-thread-1 is looping of 3 for task of 9 pool-1-thread-2 is looping of 3 for task of 8 pool-1-thread-3 is looping of 3 for task of 7 pool-1-thread-1 is looping of 4 for task of 9 pool-1-thread-2 is looping of 4 for task of 8 pool-1-thread-3 is looping of 4 for task of 7 pool-1-thread-2 is looping of 5 for task of 8 pool-1-thread-3 is looping of 5 for task of 7 pool-1-thread-1 is looping of 5 for task of 9 pool-1-thread-2 is looping of 6 for task of 8 pool-1-thread-1 is looping of 6 for task of 9 pool-1-thread-3 is looping of 6 for task of 7 pool-1-thread-3 is looping of 7 for task of 7 pool-1-thread-1 is looping of 7 for task of 9 pool-1-thread-2 is looping of 7 for task of 8 pool-1-thread-3 is looping of 8 for task of 7 pool-1-thread-1 is looping of 8 for task of 9 pool-1-thread-2 is looping of 8 for task of 8 pool-1-thread-3 is looping of 9 for task of 7 pool-1-thread-2 is looping of 9 for task of 8 pool-1-thread-1 is looping of 9 for task of 9
定長執行緒池的大小最好根據系統資源進行設定。如Runtime.getRuntime().availableProcessors()
1.2 newFixedThreadPool
建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
public class ThreadPoolTest { public static void main(String[] args) { //固定執行緒池 ExecutorService threadPool = Executors.newSingleThreadExecutor(); for (int i = 1; i < 10; i++) { int finalI = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j < 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + finalI ); } } }); } } }
pool-1-thread-1 is looping of 1 for task of 1 pool-1-thread-1 is looping of 2 for task of 1 pool-1-thread-1 is looping of 3 for task of 1 pool-1-thread-1 is looping of 4 for task of 1 pool-1-thread-1 is looping of 5 for task of 1 pool-1-thread-1 is looping of 6 for task of 1 pool-1-thread-1 is looping of 7 for task of 1 pool-1-thread-1 is looping of 8 for task of 1 pool-1-thread-1 is looping of 9 for task of 1 pool-1-thread-1 is looping of 1 for task of 2 pool-1-thread-1 is looping of 2 for task of 2 pool-1-thread-1 is looping of 3 for task of 2 pool-1-thread-1 is looping of 4 for task of 2 pool-1-thread-1 is looping of 5 for task of 2 pool-1-thread-1 is looping of 6 for task of 2 pool-1-thread-1 is looping of 7 for task of 2 pool-1-thread-1 is looping of 8 for task of 2 pool-1-thread-1 is looping of 9 for task of 2 pool-1-thread-1 is looping of 1 for task of 3 pool-1-thread-1 is looping of 2 for task of 3 pool-1-thread-1 is looping of 3 for task of 3 pool-1-thread-1 is looping of 4 for task of 3 pool-1-thread-1 is looping of 5 for task of 3 pool-1-thread-1 is looping of 6 for task of 3 pool-1-thread-1 is looping of 7 for task of 3 pool-1-thread-1 is looping of 8 for task of 3 pool-1-thread-1 is looping of 9 for task of 3 pool-1-thread-1 is looping of 1 for task of 4 pool-1-thread-1 is looping of 2 for task of 4 pool-1-thread-1 is looping of 3 for task of 4 pool-1-thread-1 is looping of 4 for task of 4 pool-1-thread-1 is looping of 5 for task of 4 pool-1-thread-1 is looping of 6 for task of 4 pool-1-thread-1 is looping of 7 for task of 4 pool-1-thread-1 is looping of 8 for task of 4 pool-1-thread-1 is looping of 9 for task of 4 pool-1-thread-1 is looping of 1 for task of 5 pool-1-thread-1 is looping of 2 for task of 5 pool-1-thread-1 is looping of 3 for task of 5 pool-1-thread-1 is looping of 4 for task of 5 pool-1-thread-1 is looping of 5 for task of 5 pool-1-thread-1 is looping of 6 for task of 5 pool-1-thread-1 is looping of 7 for task of 5 pool-1-thread-1 is looping of 8 for task of 5 pool-1-thread-1 is looping of 9 for task of 5 pool-1-thread-1 is looping of 1 for task of 6 pool-1-thread-1 is looping of 2 for task of 6 pool-1-thread-1 is looping of 3 for task of 6 pool-1-thread-1 is looping of 4 for task of 6 pool-1-thread-1 is looping of 5 for task of 6 pool-1-thread-1 is looping of 6 for task of 6 pool-1-thread-1 is looping of 7 for task of 6 pool-1-thread-1 is looping of 8 for task of 6 pool-1-thread-1 is looping of 9 for task of 6 pool-1-thread-1 is looping of 1 for task of 7 pool-1-thread-1 is looping of 2 for task of 7 pool-1-thread-1 is looping of 3 for task of 7 pool-1-thread-1 is looping of 4 for task of 7 pool-1-thread-1 is looping of 5 for task of 7 pool-1-thread-1 is looping of 6 for task of 7 pool-1-thread-1 is looping of 7 for task of 7 pool-1-thread-1 is looping of 8 for task of 7 pool-1-thread-1 is looping of 9 for task of 7 pool-1-thread-1 is looping of 1 for task of 8 pool-1-thread-1 is looping of 2 for task of 8 pool-1-thread-1 is looping of 3 for task of 8 pool-1-thread-1 is looping of 4 for task of 8 pool-1-thread-1 is looping of 5 for task of 8 pool-1-thread-1 is looping of 6 for task of 8 pool-1-thread-1 is looping of 7 for task of 8 pool-1-thread-1 is looping of 8 for task of 8 pool-1-thread-1 is looping of 9 for task of 8 pool-1-thread-1 is looping of 1 for task of 9 pool-1-thread-1 is looping of 2 for task of 9 pool-1-thread-1 is looping of 3 for task of 9 pool-1-thread-1 is looping of 4 for task of 9 pool-1-thread-1 is looping of 5 for task of 9 pool-1-thread-1 is looping of 6 for task of 9 pool-1-thread-1 is looping of 7 for task of 9 pool-1-thread-1 is looping of 8 for task of 9 pool-1-thread-1 is looping of 9 for task of 9
結果依次輸出,相當於順序執行各個任務。
現行大多數GUI程式都是單執行緒的。Android中單執行緒可用於ofollow,noindex">資料庫操作 ,檔案操作,應用批量安裝,應用批量刪除等不適合併發但可能IO阻塞性及影響UI執行緒響應的操作。
1.3 newCachedThreadPool
建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒
public class ThreadPoolTest { public static void main(String[] args) { //固定執行緒池 ExecutorService threadPool = Executors.newCachedThreadPool(); for (int i = 1; i < 10; i++) { int finalI = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j < 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + finalI ); } } }); } } }
pool-1-thread-2 is looping of 1 for task of 2 pool-1-thread-1 is looping of 1 for task of 1 pool-1-thread-8 is looping of 1 for task of 8 pool-1-thread-9 is looping of 1 for task of 9 pool-1-thread-6 is looping of 1 for task of 6 pool-1-thread-3 is looping of 1 for task of 3 pool-1-thread-7 is looping of 1 for task of 7 pool-1-thread-4 is looping of 1 for task of 4 pool-1-thread-5 is looping of 1 for task of 5 pool-1-thread-6 is looping of 2 for task of 6 pool-1-thread-5 is looping of 2 for task of 5 pool-1-thread-2 is looping of 2 for task of 2 pool-1-thread-1 is looping of 2 for task of 1 pool-1-thread-7 is looping of 2 for task of 7 pool-1-thread-8 is looping of 2 for task of 8 pool-1-thread-3 is looping of 2 for task of 3 pool-1-thread-9 is looping of 2 for task of 9 pool-1-thread-4 is looping of 2 for task of 4 pool-1-thread-5 is looping of 3 for task of 5 pool-1-thread-9 is looping of 3 for task of 9 pool-1-thread-1 is looping of 3 for task of 1 pool-1-thread-2 is looping of 3 for task of 2 pool-1-thread-8 is looping of 3 for task of 8 pool-1-thread-3 is looping of 3 for task of 3 pool-1-thread-7 is looping of 3 for task of 7 pool-1-thread-6 is looping of 3 for task of 6 pool-1-thread-4 is looping of 3 for task of 4 pool-1-thread-2 is looping of 4 for task of 2 pool-1-thread-6 is looping of 4 for task of 6 pool-1-thread-4 is looping of 4 for task of 4 pool-1-thread-7 is looping of 4 for task of 7 pool-1-thread-1 is looping of 4 for task of 1 pool-1-thread-9 is looping of 4 for task of 9 pool-1-thread-3 is looping of 4 for task of 3 pool-1-thread-5 is looping of 4 for task of 5 pool-1-thread-8 is looping of 4 for task of 8 pool-1-thread-6 is looping of 5 for task of 6 pool-1-thread-9 is looping of 5 for task of 9 pool-1-thread-5 is looping of 5 for task of 5 pool-1-thread-8 is looping of 5 for task of 8 pool-1-thread-3 is looping of 5 for task of 3 pool-1-thread-1 is looping of 5 for task of 1 pool-1-thread-7 is looping of 5 for task of 7 pool-1-thread-4 is looping of 5 for task of 4 pool-1-thread-2 is looping of 5 for task of 2 pool-1-thread-6 is looping of 6 for task of 6 pool-1-thread-2 is looping of 6 for task of 2 pool-1-thread-4 is looping of 6 for task of 4 pool-1-thread-7 is looping of 6 for task of 7 pool-1-thread-3 is looping of 6 for task of 3 pool-1-thread-1 is looping of 6 for task of 1 pool-1-thread-5 is looping of 6 for task of 5 pool-1-thread-8 is looping of 6 for task of 8 pool-1-thread-9 is looping of 6 for task of 9 pool-1-thread-4 is looping of 7 for task of 4 pool-1-thread-3 is looping of 7 for task of 3 pool-1-thread-5 is looping of 7 for task of 5 pool-1-thread-1 is looping of 7 for task of 1 pool-1-thread-9 is looping of 7 for task of 9 pool-1-thread-8 is looping of 7 for task of 8 pool-1-thread-7 is looping of 7 for task of 7 pool-1-thread-6 is looping of 7 for task of 6 pool-1-thread-2 is looping of 7 for task of 2 pool-1-thread-9 is looping of 8 for task of 9 pool-1-thread-5 is looping of 8 for task of 5 pool-1-thread-7 is looping of 8 for task of 7 pool-1-thread-1 is looping of 8 for task of 1 pool-1-thread-3 is looping of 8 for task of 3 pool-1-thread-4 is looping of 8 for task of 4 pool-1-thread-8 is looping of 8 for task of 8 pool-1-thread-6 is looping of 8 for task of 6 pool-1-thread-2 is looping of 8 for task of 2 pool-1-thread-5 is looping of 9 for task of 5 pool-1-thread-2 is looping of 9 for task of 2 pool-1-thread-4 is looping of 9 for task of 4 pool-1-thread-6 is looping of 9 for task of 6 pool-1-thread-8 is looping of 9 for task of 8 pool-1-thread-3 is looping of 9 for task of 3 pool-1-thread-1 is looping of 9 for task of 1 pool-1-thread-7 is looping of 9 for task of 7 pool-1-thread-9 is looping of 9 for task of 9
執行緒池為無限大,當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的執行緒,而不用每次新建執行緒。
1.4 newScheduledThreadPool
public class ThreadPoolTest { public static void main(String[] args) { System.out.println("init"); Executors.newScheduledThreadPool(3).schedule( new Runnable() { @Override public void run() { System.out.println("Done"); } }, 3, TimeUnit.SECONDS ); } }
init Done
表示延遲3秒執行。
定期執行
public class ThreadPoolTest { public static void main(String[] args) { Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("每三秒執行一次"); } },2,3,TimeUnit.SECONDS); } }
每三秒執行一次 每三秒執行一次 每三秒執行一次 每三秒執行一次 省略...
2 關閉執行緒池
shutdown()
public class ThreadPoolTest { public static void main(String[] args) { //固定執行緒池 ExecutorService threadPool = Executors.newFixedThreadPool(3); //快取執行緒池 池中的執行緒數量 //ExecutorService threadPool = Executors.newCachedThreadPool(); //單個執行緒 //ExecutorService threadPool = Executors.newSingleThreadExecutor(); for (int i = 1; i < 10; i++) { int finalI = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j < 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + finalI ); } } }); } threadPool.shutdown(); } }
pool-1-thread-1 is looping of 1 for task of 1 pool-1-thread-2 is looping of 1 for task of 2 pool-1-thread-3 is looping of 1 for task of 3 pool-1-thread-1 is looping of 2 for task of 1 pool-1-thread-3 is looping of 2 for task of 3 pool-1-thread-2 is looping of 2 for task of 2 pool-1-thread-1 is looping of 3 for task of 1 pool-1-thread-2 is looping of 3 for task of 2 pool-1-thread-3 is looping of 3 for task of 3 pool-1-thread-1 is looping of 4 for task of 1 pool-1-thread-3 is looping of 4 for task of 3 pool-1-thread-2 is looping of 4 for task of 2 pool-1-thread-3 is looping of 5 for task of 3 pool-1-thread-1 is looping of 5 for task of 1 pool-1-thread-2 is looping of 5 for task of 2 pool-1-thread-3 is looping of 6 for task of 3 pool-1-thread-1 is looping of 6 for task of 1 pool-1-thread-2 is looping of 6 for task of 2 pool-1-thread-3 is looping of 7 for task of 3 pool-1-thread-1 is looping of 7 for task of 1 pool-1-thread-2 is looping of 7 for task of 2 pool-1-thread-3 is looping of 8 for task of 3 pool-1-thread-1 is looping of 8 for task of 1 pool-1-thread-2 is looping of 8 for task of 2 pool-1-thread-1 is looping of 9 for task of 1 pool-1-thread-3 is looping of 9 for task of 3 pool-1-thread-2 is looping of 9 for task of 2 pool-1-thread-1 is looping of 1 for task of 4 pool-1-thread-3 is looping of 1 for task of 5 pool-1-thread-2 is looping of 1 for task of 6 pool-1-thread-1 is looping of 2 for task of 4 pool-1-thread-3 is looping of 2 for task of 5 pool-1-thread-2 is looping of 2 for task of 6 pool-1-thread-1 is looping of 3 for task of 4 pool-1-thread-3 is looping of 3 for task of 5 pool-1-thread-2 is looping of 3 for task of 6 pool-1-thread-1 is looping of 4 for task of 4 pool-1-thread-3 is looping of 4 for task of 5 pool-1-thread-2 is looping of 4 for task of 6 pool-1-thread-3 is looping of 5 for task of 5 pool-1-thread-1 is looping of 5 for task of 4 pool-1-thread-2 is looping of 5 for task of 6 pool-1-thread-3 is looping of 6 for task of 5 pool-1-thread-1 is looping of 6 for task of 4 pool-1-thread-2 is looping of 6 for task of 6 pool-1-thread-3 is looping of 7 for task of 5 pool-1-thread-1 is looping of 7 for task of 4 pool-1-thread-2 is looping of 7 for task of 6 pool-1-thread-3 is looping of 8 for task of 5 pool-1-thread-1 is looping of 8 for task of 4 pool-1-thread-2 is looping of 8 for task of 6 pool-1-thread-3 is looping of 9 for task of 5 pool-1-thread-1 is looping of 9 for task of 4 pool-1-thread-2 is looping of 9 for task of 6 pool-1-thread-1 is looping of 1 for task of 8 pool-1-thread-2 is looping of 1 for task of 9 pool-1-thread-3 is looping of 1 for task of 7 pool-1-thread-1 is looping of 2 for task of 8 pool-1-thread-2 is looping of 2 for task of 9 pool-1-thread-3 is looping of 2 for task of 7 pool-1-thread-1 is looping of 3 for task of 8 pool-1-thread-2 is looping of 3 for task of 9 pool-1-thread-3 is looping of 3 for task of 7 pool-1-thread-1 is looping of 4 for task of 8 pool-1-thread-2 is looping of 4 for task of 9 pool-1-thread-3 is looping of 4 for task of 7 pool-1-thread-2 is looping of 5 for task of 9 pool-1-thread-3 is looping of 5 for task of 7 pool-1-thread-1 is looping of 5 for task of 8 pool-1-thread-2 is looping of 6 for task of 9 pool-1-thread-3 is looping of 6 for task of 7 pool-1-thread-1 is looping of 6 for task of 8 pool-1-thread-2 is looping of 7 for task of 9 pool-1-thread-3 is looping of 7 for task of 7 pool-1-thread-1 is looping of 7 for task of 8 pool-1-thread-3 is looping of 8 for task of 7 pool-1-thread-1 is looping of 8 for task of 8 pool-1-thread-2 is looping of 8 for task of 9 pool-1-thread-3 is looping of 9 for task of 7 pool-1-thread-1 is looping of 9 for task of 8 pool-1-thread-2 is looping of 9 for task of 9
shutdownNow
public class ThreadPoolTest { public static void main(String[] args) { //固定執行緒池 ExecutorService threadPool = Executors.newFixedThreadPool(3); //快取執行緒池 池中的執行緒數量 //ExecutorService threadPool = Executors.newCachedThreadPool(); //單個執行緒 //ExecutorService threadPool = Executors.newSingleThreadExecutor(); for (int i = 1; i < 10; i++) { int finalI = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j < 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + finalI ); } } }); } threadPool.shutdownNow(); } }
java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at ThreadPoolTest$1.run(ThreadPoolTest.java:23) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) java.lang.InterruptedException: sleep interrupted pool-1-thread-3 is looping of 1 for task of 3 at java.lang.Thread.sleep(Native Method) at ThreadPoolTest$1.run(ThreadPoolTest.java:23) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) pool-1-thread-2 is looping of 1 for task of 2 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at ThreadPoolTest$1.run(ThreadPoolTest.java:23) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) pool-1-thread-1 is looping of 1 for task of 1 pool-1-thread-3 is looping of 2 for task of 3 pool-1-thread-1 is looping of 2 for task of 1 pool-1-thread-2 is looping of 2 for task of 2 pool-1-thread-2 is looping of 3 for task of 2 pool-1-thread-1 is looping of 3 for task of 1 pool-1-thread-3 is looping of 3 for task of 3 pool-1-thread-2 is looping of 4 for task of 2 pool-1-thread-3 is looping of 4 for task of 3 pool-1-thread-1 is looping of 4 for task of 1 pool-1-thread-2 is looping of 5 for task of 2 pool-1-thread-1 is looping of 5 for task of 1 pool-1-thread-3 is looping of 5 for task of 3 pool-1-thread-1 is looping of 6 for task of 1 pool-1-thread-2 is looping of 6 for task of 2 pool-1-thread-3 is looping of 6 for task of 3 pool-1-thread-1 is looping of 7 for task of 1 pool-1-thread-3 is looping of 7 for task of 3 pool-1-thread-2 is looping of 7 for task of 2 pool-1-thread-1 is looping of 8 for task of 1 pool-1-thread-3 is looping of 8 for task of 3 pool-1-thread-2 is looping of 8 for task of 2 pool-1-thread-3 is looping of 9 for task of 3 pool-1-thread-2 is looping of 9 for task of 2 pool-1-thread-1 is looping of 9 for task of 1
2.1 shutdown和shutdownNow的區別
shutdown只是將執行緒池的狀態設定為SHUTWDOWN狀態,正在執行的任務會繼續執行下去,沒有被執行的則中斷。而shutdownNow則是將執行緒池的狀態設定為STOP,正在執行的任務則被停止,沒被執行任務的則返回。
2.3 原始碼分析shutdown和shutdownNow
1.shutdown原始碼
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(SHUTDOWN); interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
2.shutdownNow原始碼
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }
從原始碼可以很清晰的看出兩者的區別,shutdown使用了以後會置狀態為SHUTDOWN,而shutdownNow為STOP。此外,shutdownNow會返回任務列表。
2.3 執行緒狀態知識延伸
在ThreadPoolExecutor中定義了關於執行緒狀態的幾個變數如下:
// runState is stored in the high-order bits
private static final int RUNNING= -1 << COUNT_BITS;
private static final int SHUTDOWN=0 << COUNT_BITS;
private static final int STOP=1 << COUNT_BITS;
private static final int TIDYING=2 << COUNT_BITS;
private static final int TERMINATED =3 << COUNT_BITS;
1.當建立執行緒池後,初始時,執行緒池處於RUNNING狀態,此時執行緒池中的任務為0;
2.如果呼叫了shutdown()方法,則執行緒池處於SHUTDOWN狀態,此時執行緒池不能夠接受新的任務,它會等待所有任務執行完畢;
3.如果呼叫了shutdownNow()方法,則執行緒池處於STOP狀態,此時執行緒池不能接受新的任務,並且會去嘗試終止正在執行的任務;
4.當所有的任務已終止,ctl記錄的”任務數量”為0,執行緒池會變為TIDYING狀態。接著會執行terminated()函式。
5.執行緒池處在TIDYING狀態時,執行完terminated()之後,就會由 TIDYING -> TERMINATED,執行緒池被設定為TERMINATED狀態。
總結
執行緒池的作用:
執行緒池作用就是限制系統中執行執行緒的數量。
根據系統的環境情況,可以自動或手動設定執行緒數量,達到執行的最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。用執行緒池控制執行緒數量,其他執行緒排隊等候。一個任務執行完畢,再從佇列的中取最前面的任務開始執行。若佇列中沒有等待程序,執行緒池的這一資源處於等待。當一個新任務需要執行時,如果執行緒池 中有等待的工作執行緒,就可以開始運行了;否則進入等待佇列。
為什麼要用執行緒池:
1.減少了建立和銷燬執行緒的次數,每個工作執行緒都可以被重複利用,可執行多個任務。
2.可以根據系統的承受能力,調整執行緒池中工作線執行緒的數目,防止因為消耗過多的記憶體,而把伺服器累趴下(每個執行緒需要大約1MB記憶體,執行緒開的越多,消耗的記憶體也就越大,最後宕機)。