一个线程提交到线程池的处理流程如下图摘要:1)初始化线程池,线程池初始化时并没有创建corePoolSize数目的核心线程,而是惰性加载的方式。等有任务后才创建核心线程。
1)初始化线程池,线程池初始化时并没有创建corePoolSize数目的核心线程,而是惰性加载的方式。等有任务后才创建核心线程。
2)如果线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的核心线程来处理被添加的任务。
3)如果线程池中的数量大于等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。
4)如果线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的非核心线程来处理被添加的任务。
5)如果此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
import java.util.concurrent.*;publicclassThreadPoolExecutorDemo {publicstaticvoidmain(String args) {// 创建一个线程池对象 ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 10, TimeUnit.SECONDS,new ArrayBlockingQueue(5), Executors.defaultThreadFactory,new ThreadPoolExecutor.AbortPolicy);// 提交多个任务到线程池中for (int i = 1; i executor.execute( -> {try { Thread.sleep(1000); System.out.println(Thread.currentThread.getName + " is running"); } catch (InterruptedException e) { e.printStackTrace; } }); }// 关闭线程池 executor.shutdown; }}1.AbortPolicy特点:不执行此任务,而且直接抛出一个运行时异常。
应用场景:适用于对任务丢失敏感的场景,当线程池无法接受新任务时,希望立即知道并处理该异常。
2.DiscardPolicy特点:新任务被提交后直接被丢弃掉,并且不会抛出异常,无法感知到这个任务会被丢弃,可能造成数据丢失。
使用场景:适用于对任务丢失不敏感的场景,当线程池无法接受新任务时,简单地丢弃被拒绝的任务。
3.DiscardOldestPolicy特点:会丢弃任务队列中的头结点,通常是存活时间最长并且未被处理的任务。
使用场景:适用于对新任务优先级较高的场景,当线程池无法接受新任务时,会丢弃一些等待时间较长的旧任务,以便接受新任务。
4.CallerRunsPolicy特点:当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。不会抛出异常。
使用场景:适用于希望调用者自己处理被拒绝的任务的场景,通常是由调用者自身的线程来执行被拒绝的任务。
优点:
1)新提交的任务不会被丢弃,这不会造成业务损失。
2)此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。提交任务的线程需要负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。
来源:传奇的巨星马大仙