🔥博客主页: 【小扳_-CSDN博客】**
❤感谢大家点赞👍收藏⭐评论✍**
文章目录
[1.0 线程池概述](#1.0 线程池概述)
[1.1 线程池的优点](#1.1 线程池的优点)
[1.2 不使用线程池的问题](#1.2 不使用线程池的问题)
[1.3 线程池的工作原理图](#1.3 线程池的工作原理图)
[1.4 如何创建线程池?](#1.4 如何创建线程池?)
[2.0 通过 ThreadPoolExecutor 类自定义创建线程池](#2.0 通过 ThreadPoolExecutor 类自定义创建线程池)
[2.1 ThreadPoolExecutor 构造器](#2.1 ThreadPoolExecutor 构造器)
[3.0 线程池处理 Runnable 任务](#3.0 线程池处理 Runnable 任务)
[3.1 通过 void execute(Runnable command) 方法](#3.1 通过 void execute(Runnable command) 方法)
[3.2 通过 void shutdown() 方法](#3.2 通过 void shutdown() 方法)
[3.3 通过 List](#3.3 通过 List) [shutdownNow() 方法](#shutdownNow() 方法)
[3.4 临时线程什么时候创建?](#3.4 临时线程什么时候创建?)
[3.5 什么时候会开始拒绝新任务?](#3.5 什么时候会开始拒绝新任务?)
[4.0 线程池处理 Callable 任务](#4.0 线程池处理 Callable 任务)
[4.1 通过 submit() 方法](#4.1 通过 submit() 方法)
[5.0 通过 Executors 工具类创建出线程池](#5.0 通过 Executors 工具类创建出线程池)
[5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池](#5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池)
[5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池](#5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池)
[5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池](#5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池)
[6.0 新任务拒绝策略](#6.0 新任务拒绝策略)
[6.1 AbortPolicy(默认策略,直接抛出异常)](#6.1 AbortPolicy(默认策略,直接抛出异常))
[6.2 DiscardPolicy(直接丢弃任务)](#6.2 DiscardPolicy(直接丢弃任务))
[6.3 CallerRunsPolicy(由调用线程执行任务)](#6.3 CallerRunsPolicy(由调用线程执行任务))
[6.4 DiscardOldestPolicy(丢弃队列中最旧的任务)](#6.4 DiscardOldestPolicy(丢弃队列中最旧的任务))
1.0 线程池概述
线程池是一种重要的并发编程机制,用于管理和复用线程,以提高应用程序的性能和资源利用率。
线程池就是一个可以复用线程的技术。
简单来说,线程池起到了复用线程的作用。假如不用线程池的话,用线程来处理任务,来多少任务就要创建多少了线程,这就会导致线程堆积,而且线程的创建和销毁虽然比进程的消耗低,但是对于大量的线程进行创建和销毁,就会导致消耗更大了,这里的消耗主要是指 CPU 消耗。还有一方面的原因,如果手动创建线程的话,需要通过内核进行创建;若在线程池中取出线程,不需要通过内核,直接通过用户态即可。所以总结来说,线程池中的线程一次创建完毕之后,不执行任务的时候,核心线程就存放在线程池中,临时线程会有一个时间的存放,超过了规定的时间就会自动销毁;需要执行任务的时候,就会从线程池中取出线程,此时不需要通过内核态,直接是通过用户态。用完之后,将线程放回到线程池中,等待下一个任务。
1.1 线程池的优点
1)降低线程创建和销毁的开销。通过重用线程从而减少频繁创建和开销线程所带来的性能损耗。
2)控制并发线程数量。通过设定线程池的大小和配置,可以限制并发线程的数量,避免系统资源耗尽。
1.2 不使用线程池的问题
假设用户发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。
1.3 线程池的工作原理图
1.4 如何创建线程池?
常见的创建线程池的方式有两种:
1)通过已经实现 ExecutorService 接口的 ThreadPoolExecutor 类来创建出线程池。
2)通过 Executors 工具类创建出线程池。
2.0 通过 ThreadPoolExecutor 类自定义创建线程池
可以直接使用 ThreadPoolExecutor 类来创建自定义的线程池,通过指定核心线程数、最大线程数、工作队列等参数来满足特定的需求。这种方法更灵活,可以根据具体场景进行定制化配置。
2.1 ThreadPoolExecutor 构造器
1)参数一:corePoolSize:指定线程池的核心线程的数量。
2)参数二:maximumPoolSize:指定线程池的最大线程数量。
3)参数三:keepAliveTime:指定临时线程的存活时间。
4)参数四:unit:指定临时线程的存活时间单位(秒、分、时、天)。
5)参数五:workQueue:指定线程池的任务队列。
6)参数六:threadFactory:指定线程池的线程工厂(创建线程的地方)。
7)参数七:handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满的时候,新任务来了该怎么处理)。
具体创建线程池代码如下:
javaimport java.util.concurrent.*; public class CreateThreadPoolExecutor { public Executor threadPool = new ThreadPoolExecutor( 3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常 }
3.0 线程池处理 Runnable 任务
线程池通过执行 Runnable 任务来实现多线程处理。将实现 Runnable 接口的任务提交给线程池,线程池会根据配置的参数调度任务执行。核心线程数内的任务会立即执行,超出核心线程数的任务会被放入任务队列中。如果任务队列已满,且线程数未达到最大线程数,线程池会创建新线程执行任务。线程池管理线程的生命周期,重用线程以减少线程创建和销毁的开销。
ExecutorService 的常用方法:
3.1 通过 void execute(Runnable command) 方法
将 Runnable 类型的任务交给线程池,线程池就会自动创建线程,自动执行 run() 方法且自动启动线程。
代码如下:
javaimport java.util.concurrent.*; public class CreateThreadPoolExecutor { public static void main(String[] args) { Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常 //定义出Runnable类型的任务 MyRunnable myRunnable1 = new MyRunnable(); MyRunnable myRunnable2 = new MyRunnable(); //将该任务提交给线程池 threadPool.execute(myRunnable1); threadPool.execute(myRunnable2); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在执行"); } }
运行结果:
需要注意的是,任务执行完毕之后,线程池中的线程不会销毁,还在继续运行中。
3.2 通过 void shutdown() 方法
等待全部任务执行完毕后,再关闭线程池。想要手动关闭线程池中的线程,可以用该方法,等待全部任务都执行后才会关闭。
代码如下:
javaimport java.util.concurrent.*; public class CreateThreadPoolExecutor { public static void main(String[] args) { Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常 //定义出Runnable类型的任务 MyRunnable myRunnable1 = new MyRunnable(); MyRunnable myRunnable2 = new MyRunnable(); //将该任务提交给线程池 threadPool.execute(myRunnable1); threadPool.execute(myRunnable2); //当全部任务都执行结束后,才会关闭 ((ThreadPoolExecutor) threadPool).shutdown(); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在执行"); } }
运行结果:
3.3 通过 List<Runnable> shutdownNow() 方法
立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务。先比较与以上的方法,当前的方法就很"激进"了。不管任务结束与否,都会关闭线程池中的线程。
代码如下:
javaimport java.util.List; import java.util.concurrent.*; public class CreateThreadPoolExecutor { public static void main(String[] args) { Executor threadPool = new ThreadPoolExecutor( 3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常 //定义出Runnable类型的任务 MyRunnable myRunnable1 = new MyRunnable(); MyRunnable myRunnable2 = new MyRunnable(); MyRunnable myRunnable3 = new MyRunnable(); MyRunnable myRunnable4 = new MyRunnable(); MyRunnable myRunnable5 = new MyRunnable(); //将该任务提交给线程池 threadPool.execute(myRunnable1); threadPool.execute(myRunnable2); threadPool.execute(myRunnable3); threadPool.execute(myRunnable4); threadPool.execute(myRunnable5); //还没执行完的任务会交给l链表 List<Runnable> l = ((ThreadPoolExecutor) threadPool).shutdownNow(); for (int i = 0; i < l.size(); i++) { System.out.println("还没来得及执行的任务:" + l.get(i)); } } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在执行"); } }
运行结果:
3.4 临时线程什么时候创建?
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
代码如下:
javaimport java.util.concurrent.*; public class T { public static void main(String[] args) { Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常 //定义出Runnable类型的任务,此时该三个任务都被核心线程正在处理 MyRunnable myRunnable1 = new MyRunnable(); MyRunnable myRunnable2 = new MyRunnable(); MyRunnable myRunnable3 = new MyRunnable(); //这里还没到临时线程创建的时机,被放入到任务队列中等待被核心线程执行 MyRunnable myRunnable4 = new MyRunnable(); MyRunnable myRunnable5 = new MyRunnable(); MyRunnable myRunnable6 = new MyRunnable(); MyRunnable myRunnable7 = new MyRunnable(); //此时到了临时线程创建的时机了,核心线程都在满,队列已经满了 //创建出第一个临时线程 MyRunnable myRunnable8 = new MyRunnable(); //创建出第二个临时线程 MyRunnable myRunnable9 = new MyRunnable(); //将该任务提交给线程池 threadPool.execute(myRunnable1); threadPool.execute(myRunnable2); threadPool.execute(myRunnable3); threadPool.execute(myRunnable4); threadPool.execute(myRunnable5); threadPool.execute(myRunnable6); threadPool.execute(myRunnable7); threadPool.execute(myRunnable8); threadPool.execute(myRunnable9); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行" + this); try { //在这里等待10s Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
运行结果:
当前的核心线程为 3 ,最大线程为 5 且任务队列有四个位置。当核心线程达到 3 时,且任务队列满 4 个了,还能创建临时线程时提交新任务就可以创建出临时线程了。
3.5 什么时候会开始拒绝新任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。
代码如下:
javaimport java.util.concurrent.*; public class T { public static void main(String[] args) { Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量 5,//最大线程数量 8,//临时线程存活时间 TimeUnit.SECONDS,//临时线程存活时间单位 new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4 Executors.defaultThreadFactory(),//线程工厂, //用到了Executors工具类来创建默认线程工厂 new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常 //定义出Runnable类型的任务,此时该三个任务都被核心线程正在处理 MyRunnable myRunnable1 = new MyRunnable(); MyRunnable myRunnable2 = new MyRunnable(); MyRunnable myRunnable3 = new MyRunnable(); //这里还没到临时线程创建的时机,被放入到任务队列中等待被核心线程执行 MyRunnable myRunnable4 = new MyRunnable(); MyRunnable myRunnable5 = new MyRunnable(); MyRunnable myRunnable6 = new MyRunnable(); MyRunnable myRunnable7 = new MyRunnable(); //此时到了临时线程创建的时机了,核心线程都在满,队列已经满了 //创建出第一个临时线程 MyRunnable myRunnable8 = new MyRunnable(); //创建出第二个临时线程 MyRunnable myRunnable9 = new MyRunnable(); //此时核心线程都在忙,且队列已经占满了,再提交新任务的时候, //就会采取拒绝策略 MyRunnable myRunnable10 = new MyRunnable(); //将该任务提交给线程池 threadPool.execute(myRunnable1); threadPool.execute(myRunnable2); threadPool.execute(myRunnable3); threadPool.execute(myRunnable4); threadPool.execute(myRunnable5); threadPool.execute(myRunnable6); threadPool.execute(myRunnable7); threadPool.execute(myRunnable8); threadPool.execute(myRunnable9); threadPool.execute(myRunnable10); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行" + this); try { //在这里等待10s Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
运行结果:
拒绝策略默认是抛出异常
4.0 线程池处理 Callable 任务
处理Callable任务时,线程池可通过 submit() 方法提交 Callable 实例,并返回代表任务执行情况的 Future 。通过 Future 可以获取任务执行结果或处理异常。
ExecutorService 常见的方法:
4.1 通过 submit() 方法
提交 Callable 类型的任务给线程池,线程池会选择可用线程、自动执行 call() 方法、自动启动线程。
代码如下:
javaimport java.util.concurrent.*; public class MyCreateThreadPool { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executor = new ThreadPoolExecutor( 3, 5, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); //创建出Callable类型的实例对象 MyCallable callable1 = new MyCallable(100); MyCallable callable2 = new MyCallable(200); MyCallable callable3 = new MyCallable(300); MyCallable callable4 = new MyCallable(400); //将任务提交到线程池中 Future<String> f1 = executor.submit(callable1); Future<String> f2 = executor.submit(callable2); Future<String> f3 = executor.submit(callable3); Future<String> f4 = executor.submit(callable4); //拿到结果 System.out.println(f1.get()); System.out.println(f2.get()); System.out.println(f3.get()); System.out.println(f4.get()); } }
运行结果:
5.0 通过 Executors 工具类创建出线程池
Executors 工具类提供了创建不同类型线程池的方法,如 newFixedThreadPool 、 newCachedThreadPool、newSingleThreadExecutor 等。这些方法返回不同配置的线程池实例,可用于执行 Runnable 和 Callable 任务。通过 Executors 创建线程池,可方便地管理线程池的大小、任务队列、线程工厂等参数。注意合理选择线程池类型以满足任务需求,避免资源浪费或任务阻塞。
简单来说,Executors 工具类为我们提供了不同特点的线程池。
5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池
创建固定线程数量的线程池,如果某个线程因执行异常而结束,那么线程池会补充一个新线程代替它。
代码如下:
javaimport java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class demo1 { public static void main(String[] args) { //固定的线程池核心线程为3,临时线程为0,所以最大线程数量也就是3。 ExecutorService pool = Executors.newFixedThreadPool(3); pool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行"); } }); pool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行"); } }); pool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行"); } }); pool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "==> 正在执行"); } }); } }
运行结果:
其实 Executors.newFixedThreadPool(int nThreads) 方法的底层就是通过 ThreadPoolExecutor 类来实现创建线程池的。传入的参数就是核心线程线程数量,也为最大线程数量,因此临时线程数量为 0 。因此没有临时线程的存在,那么该线程池中的线程很固定。
如图:
5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池
线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了 60 s则会被回收掉。也就是有多少了任务线程池会根据任务数量动态创建新线程。
代码如下:
javaimport java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; public class demo2 { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); System.out.println( ((ThreadPoolExecutor)executorService).getPoolSize()); } }
通过 getPoolSize() 方法可以拿到当前线程池中线程的数量。
运行结果如下:
该方法创建出来的线程池特点为,当任务越多时候,线程池中的线程数量也会随之增加。其实这个方法的底层实现也是通过 ThreadPoolExecutor 类来实现创建线程池。
如图:
很惊奇的发现,核心线程竟然是 0 个,而临时线程数量的最大值是非常非常大的,如果线程任务执行完毕且空闲了 60 s则会被回收掉。
5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池
创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。
代码如下:
javaimport java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class demo3 { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行")); } }
运行结果:
因为该线程池中只有一个线程,所以该线程需要执行所有的任务。因此该方法创建出来的线程池特点是,只有一个线程。当然该方法的底层也是通过 ThreadPoolExecutor 类来试下创建线程池。
如图:
核心线程只有一个,最大线程也是一个,说明临时线程为零个。因此线程池中只有单一的线程。
6.0 新任务拒绝策略
常见的拒绝策略包括:AbortPolicy(默认策略,直接抛出异常)、CallerRunsPolicy(由调用线程执行任务)、DiscardPolicy(直接丢弃任务)、DiscardOldestPolicy(丢弃队列中最旧的任务)。
6.1 AbortPolicy(默认策略,直接抛出异常)
丢弃任务并抛出 RejectedExecutionExeception 异常,是默认的策略。
代码如下:
javaimport java.util.concurrent.*; public class demo1 { public static void main(String[] args) { ExecutorService executorService = new ThreadPoolExecutor( 2, 3, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), //默认拒绝新任务的策略 new ThreadPoolExecutor.AbortPolicy() ); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时会有临时线程创建 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时新任务提交的时候,会触发拒绝策略 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); } }
运行结果:
新提交的任务就被抛弃了且抛出异常。
6.2 DiscardPolicy(直接丢弃任务)
丢弃任务,但是不抛出异常,这是不推荐的做法。
代码如下:
javaimport java.util.concurrent.*; public class demo1 { public static void main(String[] args) { ExecutorService executorService = new ThreadPoolExecutor( 2, 3, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy() ); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时会有临时线程创建 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时新任务提交的时候,会触发拒绝策略 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); } }
运行结果:
6.3 CallerRunsPolicy(由调用线程执行任务)
由主线程负责调用任务的 run() 方法从而绕过线程池直接执行。
简单来说,就是交给 main 主线程执行该任务。
代码如下:
javaimport java.util.concurrent.*; public class demo1 { public static void main(String[] args) { ExecutorService executorService = new ThreadPoolExecutor( 2, 3, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() ); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时会有临时线程创建 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时新任务提交的时候,会触发拒绝策略 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); } }
6.4 DiscardOldestPolicy(丢弃队列中最旧的任务)
抛弃队列中等待最久的任务,然后把当前任务假如队列中。
javaimport java.util.concurrent.*; public class demo1 { public static void main(String[] args) { ExecutorService executorService = new ThreadPoolExecutor( 2, 3, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), //默认拒绝新任务的策略 new ThreadPoolExecutor.DiscardOldestPolicy() ); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时会有临时线程创建 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); //此时新任务提交的时候,会触发拒绝策略 executorService.execute(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { throw new RuntimeException(e); } }); } }
运行结果: