JavaEE 初阶篇-深入了解线程池(线程池创建、线程池如何处理任务)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 线程池概述

        1.1 线程池的优点

        1.2 不使用线程池的问题

        1.3 线程池的工作原理图

        1.4 如何创建线程池? 

        2.0 通过 ThreadPoolExecutor 类自定义创建线程池

        2.1 ThreadPoolExecutor 构造器

        3.0 线程池处理 Runnable 任务

        3.1 通过 void execute(Runnable command) 方法

        3.2 通过 void shutdown() 方法

        3.3 通过 List shutdownNow() 方法

        3.4 临时线程什么时候创建?

        3.5 什么时候会开始拒绝新任务?

        4.0 线程池处理 Callable 任务

        4.1 通过 submit() 方法

        5.0 通过 Executors 工具类创建出线程池

        5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池

        5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池

        5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池

        6.0 新任务拒绝策略

        6.1 AbortPolicy(默认策略,直接抛出异常)

        6.2 DiscardPolicy(直接丢弃任务)

        6.3 CallerRunsPolicy(由调用线程执行任务)

        6.4 DiscardOldestPolicy(丢弃队列中最旧的任务)


        1.0 线程池概述

        线程池是一种重要的并发编程机制,用于管理和复用线程,以提高应用程序的性能和资源利用率。

        线程池就是一个可以复用线程的技术。

        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:指定线程池的任务拒绝策略(线程都在忙,任务队列也满的时候,新任务来了该怎么处理)。

具体创建线程池代码如下:

import java.util.concurrent.*;
public class CreateThreadPoolExecutor {public Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量5,//最大线程数量8,//临时线程存活时间TimeUnit.SECONDS,//临时线程存活时间单位new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4Executors.defaultThreadFactory(),//线程工厂,//用到了Executors工具类来创建默认线程工厂new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常}

        

        3.0 线程池处理 Runnable 任务

        线程池通过执行 Runnable 任务来实现多线程处理。将实现 Runnable 接口的任务提交给线程池,线程池会根据配置的参数调度任务执行。核心线程数内的任务会立即执行,超出核心线程数的任务会被放入任务队列中。如果任务队列已满,且线程数未达到最大线程数,线程池会创建新线程执行任务。线程池管理线程的生命周期,重用线程以减少线程创建和销毁的开销。

ExecutorService 的常用方法:

        3.1 通过 void execute(Runnable command) 方法

        将 Runnable 类型的任务交给线程池,线程池就会自动创建线程,自动执行 run() 方法且自动启动线程。

代码如下:

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),//创建任务队列,最大存放任务数量为4Executors.defaultThreadFactory(),//线程工厂,//用到了Executors工具类来创建默认线程工厂new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常//定义出Runnable类型的任务MyRunnable myRunnable1 = new MyRunnable();MyRunnable myRunnable2 = new MyRunnable();//将该任务提交给线程池threadPool.execute(myRunnable1);threadPool.execute(myRunnable2);}
}
class  MyRunnable implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "正在执行");}
}

运行结果:

        需要注意的是,任务执行完毕之后,线程池中的线程不会销毁,还在继续运行中

        3.2 通过 void shutdown() 方法

        等待全部任务执行完毕后,再关闭线程池。想要手动关闭线程池中的线程,可以用该方法,等待全部任务都执行后才会关闭。

代码如下:

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),//创建任务队列,最大存放任务数量为4Executors.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{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "正在执行");}
}

运行结果:

        3.3 通过 List<Runnable> shutdownNow() 方法

        立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务。先比较与以上的方法,当前的方法就很“激进”了。不管任务结束与否,都会关闭线程池中的线程。

代码如下:

import 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),//创建任务队列,最大存放任务数量为4Executors.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{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "正在执行");}
}

运行结果:

        3.4 临时线程什么时候创建?

        新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

代码如下:

import java.util.concurrent.*;
public class T {public static void main(String[] args) {Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量5,//最大线程数量8,//临时线程存活时间TimeUnit.SECONDS,//临时线程存活时间单位new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4Executors.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{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行" + this);try {//在这里等待10sThread.sleep(10000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}

运行结果:

        当前的核心线程为 3 ,最大线程为 5 且任务队列有四个位置。当核心线程达到 3 时,且任务队列满 4 个了,还能创建临时线程时提交新任务就可以创建出临时线程了。

        3.5 什么时候会开始拒绝新任务?

        核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

代码如下:

import java.util.concurrent.*;
public class T {public static void main(String[] args) {Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量5,//最大线程数量8,//临时线程存活时间TimeUnit.SECONDS,//临时线程存活时间单位new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4Executors.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{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行" + this);try {//在这里等待10sThread.sleep(10000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}

运行结果:

        拒绝策略默认是抛出异常

        4.0 线程池处理 Callable 任务

        处理Callable任务时,线程池可通过 submit() 方法提交 Callable 实例,并返回代表任务执行情况的 Future 。通过 Future 可以获取任务执行结果或处理异常

ExecutorService 常见的方法:

        4.1 通过 submit() 方法

        提交 Callable 类型的任务给线程池,线程池会选择可用线程、自动执行 call() 方法、自动启动线程。

代码如下:

import 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) 方法来创建线程池

        创建固定线程数量的线程池,如果某个线程因执行异常而结束,那么线程池会补充一个新线程代替它。

代码如下:

import 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() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行");}});pool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行");}});pool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行");}});pool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==> 正在执行");}});}
}

运行结果:

        其实 Executors.newFixedThreadPool(int nThreads) 方法的底层就是通过 ThreadPoolExecutor 类来实现创建线程池的。传入的参数就是核心线程线程数量,也为最大线程数量,因此临时线程数量为 0 。因此没有临时线程的存在,那么该线程池中的线程很固定

如图:

        5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池

        线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了 60 s则会被回收掉。也就是有多少了任务线程池会根据任务数量动态创建新线程。

代码如下:

import 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() 方法来创建线程池

        创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。

代码如下:

import 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 异常,是默认的策略。

代码如下:

import 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(直接丢弃任务)

        丢弃任务,但是不抛出异常,这是不推荐的做法。

代码如下:

import 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 主线程执行该任务。

代码如下:

import 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(丢弃队列中最旧的任务)

        抛弃队列中等待最久的任务,然后把当前任务假如队列中。

import 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);}});}
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797536.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

撸代码时,有哪些习惯一定要坚持?

我从2011年开始做单片机开发&#xff0c;一直保持以下撸代码的习惯。 1.做好代码版本管理 有些人&#xff0c;喜欢一个程序干到底&#xff0c;直到实现全部的产品功能&#xff0c;我以前做51单片机的项目就是这样。 如果功能比较多的产品&#xff0c;我不建议这样做&#xff0…

如何搭建APP分发平台分发平台搭建教程

搭建一个APP分发平台可以帮助开发者更好地分发和管理他们的应用程序。下面是一个简要的教程&#xff0c;介绍如何搭建一个APP分发平台。 1.确定需求和功能&#xff1a;首先&#xff0c;确定你的APP分发平台的需求和功能。考虑以下几个方面&#xff1a; 用户注册和登录&#xff…

Anritsu MS9740B与MS9740A 光谱分析仪 的区别?

MS9740B与MS9740A的主要区别在于测量处理时间的缩短和对高速信号处理技术的应用。MS9740B在保持原有功能和性能的同时&#xff0c;将测量处理时间缩短了一半。这一点通过提高生产效率和减少测量及检查时间来实现&#xff0c;从而提高了光有源设备制造商的生产力。此外&#xff…

mid转MP3怎么转?一分钟搞定~

MIDI&#xff08;Musical Instrument Digital Interface&#xff09;文件格式的诞生可以追溯到上世纪80年代&#xff0c;音频技术迅速崛起。为了让不同音乐设备之间能够互相通信&#xff0c;MIDI格式成为了音乐的标准。它不同于常见的音频文件格式&#xff0c;不包含实际的声音…

浮点数在内存中的存储【详解】

浮点数在内存中的存储 浮点数存储规则小数点后数值的二进制转换float和double存储图示优化存储方案E不全为0或不全为1E全为0E全为1 浮点数存储规则 大家都知道整型数据是以补码的方式存放在内存中。以下几个概念是需要知道的&#xff1a; 原码&#xff0c;补码&#xff0c;反…

汇编语言:寻址方式在结构化数据访问中的应用——计算人均收入

有一年多没有在CSDN上发博文了。人的工作重心总是有转移的&#xff0c;庆幸一直在做着有意义的事。   今天的内容&#xff0c;是为汇编语言课程更新一个实验项目。      本方案修改自王爽编《汇编语言》第&#xff14;版P172“实验7寻址方式在结构化数据访问中的应用” …

探索未来游戏:生成式人工智能AI如何重塑你的游戏世界?

生成式人工智能&#xff08;Generative AI&#xff09;正以前所未有的速度改变着各行各业的运作模式。其中&#xff0c;游戏产业作为科技应用的前沿阵地&#xff0c;正经历着前所未有的变革。本文将探讨生成式人工智能如何重塑游戏产业&#xff0c;以及这一变革背后的深远影响。…

一、Docker部署GitLab(详细步骤)

Docker部署GitLab&#xff08;详细步骤&#xff09; 一、拉取镜像二、启动容器三、修改配置四、修改密码五、浏览器访问 一、拉取镜像 docker安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/131270071 docker pull gitlab/gitlab-ce:latest二、启动容器 …

邮件服务器:Postfix

文章目录 邮件服务器的功能与工作原理电子邮件的问题Mail server与DNS 之间的关系邮件传输所需要的组件(MTA、MUA、MDA)以及相关协议用户收信时服务器端所提供的相关协议&#xff1a;MRA电子邮件的数据内容 使用Postfix与Dovecot部署邮件系统部署基础的电子邮件系统配置Postfix…

政校企三方牵手打造新质生产力,共建城市供应链安全检测中心

​4月3日 十堰市经开区政府 x 开源网安 战略合作签约仪式 圆满完成 4月3日&#xff0c;开源网安与十堰市经济技术开发区政府、湖北工业职业技术学院、十堰市经开建投签约仪式在十堰国际会展中心圆满完成。本次签约后&#xff0c;签约方将共建十堰市智能网联汽车网络安全测试…

什么是数据治理?你都了解吗?

在当今数字化时代&#xff0c;数据已成为企业重要的战略资产。有效管理数据对于企业提高运营效率、降低成本、做出更好的决策至关重要。数据治理作为一种重要的管理方法&#xff0c;可以帮助企业确保数据的质量、安全、合规性和有效利用。 一、数据治理的定义与重要性 近日&a…

(南京观海微电子)——TFT驱动原理

TFT液晶显示器件是指在液晶显示器件的每个像素上都连接一个薄膜场效应晶体管。这个场效应管制作在液晶显示器件的玻璃上。每个场效应管独立驱动一个像素&#xff0c;从而可以实现高速度、高亮度、高对比度的显示效果。 TFT液晶显示器件的驱动特性取决于场效应管的工作特性。场效…

SpringBoot实现邮箱验证

目录 1、开启邮箱IMAP/SMTP服务&#xff0c;获取授权码 2、相关代码 1、使用配置Redis&#xff08;用于存储验证码&#xff0c;具有时效性&#xff09; 2、邮箱依赖和hutool&#xff08;用于随机生成验证码&#xff09; 3、配置Redis和邮箱信息 4、开启Redis服务 5、编写发送…

海外代理IP购买指南:住宅IP代理VS.数据中心代理IP

在选择海外IP代理服务时&#xff0c;您将面临一个关键的问题&#xff1a;是选择住宅代理IP还是数据中心代理IP&#xff1f;这两者之间存在着根本性的不同&#xff0c;涉及到性能、隐私和成本等方面的考虑。住宅代理IP通常来自真实的住宅网络连接&#xff0c;更难被检测到。数据…

Winforms中的ArgumentOutOfRangeException异常

// 定时器事件 只处理计时逻辑 每隔1000毫秒会被调用。 private void timer1_Tick(object sender, EventArgs e) {count; //记录当前秒label3.Text (time - count).ToString() " 秒"; progressBar1.Value count;if(count time){timer1.Stop(); //关闭计时Sys…

MotionBuilder 脚本执行

目录 MediaPipe_Pose_in_MotionBuilder 你可以用以下几种方式执行你的脚本&#xff1a; MediaPipe_Pose_in_MotionBuilder https://github.com/Ndgt/MediaPipe_Pose_in_MotionBuilder/blob/main/PoseLandmark.py tcp通信 https://github.com/nils-soderman/motionbuilder-s…

解决Android Studio Loading Devices问题

目录 一、解决办法&#xff08;普通&#xff09;&#xff1a; 二、解决办法的优化 三、解决办法的进一步优化 问题&#xff1a;windows 11 电脑&#xff0c;每次开机&#xff0c;打开Android Studio,都会显示Loading Devices&#xff0c;连接不上设备。 原因&#xff1a;adb…

css实现更改checkbox的样式;更改checkbox选中后的背景色;更改checkbox选中后的icon

<input class"check-input" type"checkbox"> .check-input {width: 16px;height: 16px;} /* 设置默认的checkbox样式 */input.check-input[type"checkbox"] {-webkit-appearance: none; /* 移除默认样式 */border: 1px solid #999;outl…

鹏哥C语言复习——结构体

目录 结构体声明&#xff1a; 结构体内存存储相关介绍&#xff1a; 结构体的初始化与使用&#xff1a; 结构体的初始化&#xff1a; 结构体的使用&#xff1a; 结构体对齐&#xff1a; 结构体对齐原则解释&#xff1a; 结构体对齐存在的原因&#xff1a; #pragma pack…

人工智能研究生前置知识—Anaconda与python工作环境

人工智能研究生前置知识—Anaconda与python工作环境 python环境管理 python工作环境的管理是需要满足的基本条件&#xff0c;指的是不同的python版本之间的切换。或者说是允许安装不同版本的python 解决&#xff1a;conda是一个跨平台的包管理工具&#xff0c;其环境管理功能允…