執行緒池(詳解):三大方法、七大引數、四種拒絕策略

你的龍兒發表於2020-06-26

執行緒池(重點)

一:執行緒池:三大方法,七大引數,四種拒絕策略

  池化技術:
  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 }

執行結果:

 

相關文章