线程池(详解):三大方法七大参数四种拒绝策略

Posted liangbaolong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池(详解):三大方法七大参数四种拒绝策略相关的知识,希望对你有一定的参考价值。

线程池(重点)

一:线程池:三大方法,七大参数,四种拒绝策略

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

运行结果:

技术图片

 

以上是关于线程池(详解):三大方法七大参数四种拒绝策略的主要内容,如果未能解决你的问题,请参考以下文章

线程池参数配置

线程池基本使用详解

JUC-12.1.1-线程池中七大参数 四种线程池 五大状态

线程池(中)

线程池工作原理

Java线程池中的四种拒绝策略