執行緒池(重點)
一:執行緒池:三大方法,七大引數,四種拒絕策略
池化技術:
01:程式的執行,本質 :佔用系統的資源! 優化資源的使用! =>池化技術
02:執行緒池、連線池、記憶體池、物件池///......建立、銷燬。 十分浪費資源
03:池化技術:事先準備好一些資源,有人要用,就來我這裡拿,用完之後還給我。
執行緒池的好處:
01:降低資源的消耗
02:提高響應的速度
03:方便管理
(重點)執行緒複用、可以控制最大併發數、管理執行緒
二:三大方法:
01:Executors.newSingleThreadExecutor() //單個執行緒
程式碼示例01
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具類、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 ExecutorService threadpool = Executors.newSingleThreadExecutor(); //單個執行緒 12 13 try { 14 for (int i = 0; i < 10; i++) { 15 //使用了執行緒池之後,使用執行緒池來建立執行緒 16 threadpool.execute(()->{ 17 System.out.println(Thread.currentThread().getName()+" ok"); 18 }); 19 } 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } finally { 23 //執行緒池用完,程式結束,關閉執行緒池 24 threadpool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 25 } 26 } 27 }
執行結果: (10個任務被同一個執行緒所操作)
02:newFixedThreadPool(int nThreads) //建立一個固定的執行緒池的大小
程式碼示例02
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具類、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 //最多5個執行緒同時執行,從控制檯中檢視結果 12 ExecutorService threadpool = Executors.newFixedThreadPool(5); //建立一個固定的執行緒池的大小,(5個執行緒) 13 14 try { 15 for (int i = 0; i < 10; i++) { 16 //使用了執行緒池之後,使用執行緒池來建立執行緒 17 threadpool.execute(()->{ 18 System.out.println(Thread.currentThread().getName()+" ok"); 19 }); 20 } 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } finally { 24 //執行緒池用完,程式結束,關閉執行緒池 25 threadpool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 26 } 27 } 28 }
執行結果:(最高同時有5個執行緒在執行)
03:newCachedThreadPool() //快取池,可伸縮的, 遇強則強,遇弱則弱
程式碼示例03
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具類、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 ExecutorService threadpool = Executors.newCachedThreadPool(); //快取池,可伸縮的, 遇強則強,遇弱則弱 12 13 try { 14 for (int i = 0; i < 10; i++) { 15 //使用了執行緒池之後,使用執行緒池來建立執行緒 16 threadpool.execute(()->{ 17 System.out.println(Thread.currentThread().getName()+" ok"); 18 }); 19 } 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } finally { 23 //執行緒池用完,程式結束,關閉執行緒池 24 threadpool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 25 } 26 } 27 }
執行結果:(最高同時有10個執行緒在執行,可伸縮的, 遇強則強,遇弱則弱)
三:七大引數
01:三大方法之原始碼分析:
1 (1) newSingleThreadExecutor() //單個執行緒 2 3 public static ExecutorService newSingleThreadExecutor() { 4 return new FinalizableDelegatedExecutorService 5 (new ThreadPoolExecutor(1, 1, 6 0L, TimeUnit.MILLISECONDS, 7 new LinkedBlockingQueue<Runnable>())); 8 } 9 ================================================================================== 10 (2) newFixedThreadPool(int nThreads) //建立一個固定的執行緒池的大小 11 12 public static ExecutorService newFixedThreadPool(int nThreads) { 13 return new ThreadPoolExecutor(nThreads, nThreads, 14 0L, TimeUnit.MILLISECONDS, 15 new LinkedBlockingQueue<Runnable>()); 16 } 17 =================================================================================== 18 (3) newCachedThreadPool() //快取池,可伸縮的, 遇強則強,遇弱則弱 19 20 public static ExecutorService newCachedThreadPool() { 21 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //Integer.Max_VALUE 約等於21億 //如果我們有這麼多條執行緒一起跑的話,電腦會OOM(溢位),出現問題 22 60L, TimeUnit.SECONDS, 23 new SynchronousQueue<Runnable>()); 24 } 25 ==================================================================================== 26 (4) 三大方法所公共的 ThreadPoolExecutor() 方法 27 28 ******7大引數****** 29 30 public ThreadPoolExecutor(int corePoolSize, //核心執行緒池大小 31 int maximumPoolSize, //最大核心執行緒池大小 32 long keepAliveTime, //超時了沒有人呼叫就會釋放 33 TimeUnit unit, //超時單位 34 BlockingQueue<Runnable> workQueue, //阻塞佇列 35 ThreadFactory threadFactory, //執行緒工廠,建立執行緒的,一般不用動 36 RejectedExecutionHandler handler) { //拒絕策略 37 if (corePoolSize < 0 || 38 maximumPoolSize <= 0 || 39 maximumPoolSize < corePoolSize || 40 keepAliveTime < 0) 41 throw new IllegalArgumentException(); 42 if (workQueue == null || threadFactory == null || handler == null) 43 throw new NullPointerException(); 44 this.corePoolSize = corePoolSize; 45 this.maximumPoolSize = maximumPoolSize; 46 this.workQueue = workQueue; 47 this.keepAliveTime = unit.toNanos(keepAliveTime); 48 this.threadFactory = threadFactory; 49 this.handler = handler; 50 }
阿里巴巴開發手冊中有如下規定:
例如銀行辦理業務圖:
四:四種拒絕策略:
/**
* new ThreadPoolExecutor.AbortPolicy() //銀行滿了,還有人進來,不處理這個人的,丟擲異常
* new ThreadPoolExecutor.CallerRunsPolicy() //哪來的去哪裡!
* new ThreadPoolExecutor.DiscardPolicy() //佇列滿了,丟掉任務,不會丟擲異常!
* new ThreadPoolExecutor.DiscardOldestPolicy() //佇列滿了,嘗試和最早的競爭,也不會丟擲異常
*/
五:手動(自定義)建立一個執行緒池:
程式碼示例01 new ThreadPoolExecutor.AbortPolicy() //銀行滿了,還有人進來,不處理這個人的,丟擲異常
1 package pool; 2 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.LinkedBlockingDeque; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class Demo02 { 9 public static void main(String[] args) { 10 //自定義執行緒池! 工作中只會使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心執行緒池大小 13 5, //最大核心執行緒池大小 14 3, //超時了沒有人呼叫就會釋放 15 TimeUnit.SECONDS, //超時單位 16 new LinkedBlockingDeque<>(3), //阻塞佇列 17 Executors.defaultThreadFactory(), //執行緒工廠,建立執行緒的,一般不用動 18 new ThreadPoolExecutor.AbortPolicy()); //銀行滿了,還有人進來,不處理這個人的,丟擲異常 19 20 try { 21 //最大承載數,Deque + Max (佇列執行緒數+最大執行緒數) 22 //超出 丟擲 RejectedExecutionException 異常 23 for (int i = 1; i <= 9; i++) { 24 //使用了執行緒池之後,使用執行緒池來建立執行緒 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //執行緒池用完,程式結束,關閉執行緒池 33 threadPool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 34 } 35 } 36 }
執行結果(對比):
程式碼示例02 new ThreadPoolExecutor.CallerRunsPolicy() //哪來的去哪裡
1 package pool; 2 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.LinkedBlockingDeque; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class Demo02 { 9 public static void main(String[] args) { 10 //自定義執行緒池! 工作中只會使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心執行緒池大小 13 5, //最大核心執行緒池大小 14 3, //超時了沒有人呼叫就會釋放 15 TimeUnit.SECONDS, //超時單位 16 new LinkedBlockingDeque<>(3), //阻塞佇列 17 Executors.defaultThreadFactory(), //執行緒工廠,建立執行緒的,一般不用動 18 new ThreadPoolExecutor.CallerRunsPolicy()); //哪來的去哪裡! 19 20 try { 21 //最大承載數,Deque + Max (佇列執行緒數+最大執行緒數) 22 //超出 丟擲 RejectedExecutionException 異常 23 for (int i = 1; i <= 9; i++) { 24 //使用了執行緒池之後,使用執行緒池來建立執行緒 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //執行緒池用完,程式結束,關閉執行緒池 33 threadPool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 34 } 35 } 36 }
執行結果:
程式碼示例03 new ThreadPoolExecutor.DiscardPolicy() //佇列滿了,丟掉任務,不會丟擲異常!
1 package pool; 2 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.LinkedBlockingDeque; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class Demo02 { 9 public static void main(String[] args) { 10 //自定義執行緒池! 工作中只會使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心執行緒池大小 13 5, //最大核心執行緒池大小 14 3, //超時了沒有人呼叫就會釋放 15 TimeUnit.SECONDS, //超時單位 16 new LinkedBlockingDeque<>(3), //阻塞佇列 17 Executors.defaultThreadFactory(), //執行緒工廠,建立執行緒的,一般不用動 18 new ThreadPoolExecutor.DiscardPolicy()); //佇列滿了,丟掉任務,不會丟擲異常! 19 20 try { 21 //最大承載數,Deque + Max (佇列執行緒數+最大執行緒數) 22 //超出 丟擲 RejectedExecutionException 異常 23 for (int i = 1; i <= 9; i++) { 24 //使用了執行緒池之後,使用執行緒池來建立執行緒 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //執行緒池用完,程式結束,關閉執行緒池 33 threadPool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 34 } 35 } 36 }
執行結果:
04:程式碼示例 new ThreadPoolExecutor.DiscardOldestPolicy() //佇列滿了,嘗試和最早的競爭,也不會丟擲異常
1 package pool; 2 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.LinkedBlockingDeque; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class Demo02 { 9 public static void main(String[] args) { 10 //自定義執行緒池! 工作中只會使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心執行緒池大小 13 5, //最大核心執行緒池大小 14 3, //超時了沒有人呼叫就會釋放 15 TimeUnit.SECONDS, //超時單位 16 new LinkedBlockingDeque<>(3), //阻塞佇列 17 Executors.defaultThreadFactory(), //執行緒工廠,建立執行緒的,一般不用動 18 new ThreadPoolExecutor.DiscardOldestPolicy()); //佇列滿了,嘗試和最早的競爭,也不會丟擲異常 19 20 try { 21 //最大承載數,Deque + Max (佇列執行緒數+最大執行緒數) 22 //超出 丟擲 RejectedExecutionException 異常 23 for (int i = 1; i <= 9; i++) { 24 //使用了執行緒池之後,使用執行緒池來建立執行緒 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //執行緒池用完,程式結束,關閉執行緒池 33 threadPool.shutdown(); //(為確保關閉,將關閉方法放入到finally中) 34 } 35 } 36 }
執行結果: