線程池(詳解):三大方法、七大參數、四種拒絕策略


線程池(重點)

一:線程池:三大方法,七大參數,四種拒絕策略

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

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM