ThreadPoolExecutor执行原理

线程池

基本概念: 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。

不要使用Executor创建线程池,而是通过ThreadPoolExecutor的方式创建,这样的处理方式能让编写代码的人更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors 返回的线程池对象的弊端如下:

1)FixedThreadPool和SingleThreadPool:

允许请求的队列长度为Interger.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。

2)CachedThreadPool:

允许的创建线程数量为:Interger.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

Executor创建线程的3大方法:

//Executor不建议使用,容易引发OOM
ExecutorService threadPool = Executors.newSingleThreadExecutor();//单线程
ExecutorService threadPool1 = Executors.newFixedThreadPool(5);//固定线程
ExecutorService threadPool2 = Executors.newCachedThreadPool();//可变线程

for (int i = 0; i < 10; i++) {
    threadPool2.execute(()->{
        System.out.println(Thread.currentThread().getName());
    });
}

ThreadPoolExecutor的七大参数:

核心线程数,最大线程数,超时等待时间,超时等待单位,阻塞队列,线程工厂,拒绝策略。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

执行过程:如果线程数没有超过核心线程数,那么就会用到几个开辟几个,如果大于核心线程数,但是没有超过阻塞队列的个数,那么就会等待核心线程执行完,再取阻塞队列中的执行

测试代码

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
    2,
    6,
    3,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(3),
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy()
);
try {
    for (int i = 0; i < 7; i++) {
        final int temp = i;
        threadPoolExecutor.execute(()->
                                   {
                                       try {
                                           System.out.println(Thread.currentThread().getName()+" "+temp);
                                           TimeUnit.SECONDS.sleep(1);
                                       } catch (InterruptedException e) {
                                           e.printStackTrace();
                                       }

                                   });
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    threadPoolExecutor.shutdown();
}

调整不同的循环数会出现不同的执行顺序,甚至会报错,具体是什么原理呢?下面用画图的方式描述出来。

执行过程

以核心线程数为2,最大线程数为6,阻塞队列容量为3 为例:

  • 如果要执行的任务数小于等于核心线程数:

在这里插入图片描述
如图,蓝色为待执行的任务,黄色为核心线程,当要执行的任务数小于等于核心线程数时,直接被核心线程接管:

在这里插入图片描述

  • 当待执行的任务数大于核心线程数,但是小于核心线程数+阻塞队列容量时:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
task1,task2被核心线程接管,task3进阻塞队列等待核心线程执行完毕再执行。

  • 当待执行的任务数大于核心线程数+阻塞队列容量但小于最大线程数+阻塞队列容量时:

在这里插入图片描述

因为阻塞队列已达到最大容量,剩余的线程(除去核心线程的其他线程)会被启动,用来直接接管新来的任务,当线程经过keepAliveTime还没有接到任务,则再次关闭线程。

注意:直接接管新来的任务,而不是从阻塞队列中取

  • 当待执行的任务数大于了最大线程数+阻塞队列容量时:

在这里插入图片描述
在这里插入图片描述

超出数量的任务会被拒绝,具体的拒绝策略有四种:

  • ThreadPoolExecutor.AbortPolicy():该策略是指,当有超出数量的任务来时,会抛出异常

在这里插入图片描述

  • ThreadPoolExecutor.CallerRunsPolicy();:超出数量的任务会被调用者线程执行,比如:

在这里插入图片描述
因为是主线程调用的,所以会被主线程接管。

  • ThreadPoolExecutor.DiscardPolicy();:当超出数量的任务来时,不会抛出异常

在这里插入图片描述
​ 可以看出当循环次数为10时,只执行了9个,多出的任务被丢弃。

  • ThreadPoolExecutor.DiscardOldestPolicy();:超出数量的任务会尝试去和最早执行的线程竞争
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadPoolExecutorJava 中用于管理线程池的类,它实现了 ExecutorService 接口。它可以帮助我们更方便地管理和调度多线程任务的执行。 下面是 ThreadPoolExecutor原理概述: 1. 构造函数:ThreadPoolExecutor 的构造函数接收一些参数,包括核心线程数、最大线程数、任务队列、线程工厂、拒绝策略等。通过这些参数,我们可以配置线程池的大小和行为。 2. 核心线程池:ThreadPoolExecutor 会首先创建核心线程池。核心线程池中的线程数量不会超过核心线程数的设定,即使线程处于空闲状态也不会被回收。 3. 任务队列:当提交一个任务时,如果核心线程池已满,任务会被放入任务队列中等待执行ThreadPoolExecutor 提供了多种类型的任务队列,如无界队列和有界队列等,可以根据需求进行选择。 4. 最大线程数控制:当任务队列已满时,ThreadPoolExecutor 会根据最大线程数的设定来创建新的线程,直到达到最大线程数。超过最大线程数的任务将会根据指定的拒绝策略进行处理。 5. 执行任务:当有任务可执行时,ThreadPoolExecutor 会从任务队列中取出任务,并将其交给一个空闲的线程执行。如果核心线程池中的线程都在执行任务,新的任务会被放入任务队列中等待。 6. 拒绝策略:当任务队列已满且达到最大线程数时,ThreadPoolExecutor 会根据指定的拒绝策略来处理无法执行的任务。常见的拒绝策略有抛出异常、丢弃任务等。 以上是 ThreadPoolExecutor 的基本原理概述。详细的源码实现可以参考 Java SDK 的源码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值