线程池ThreadPoolExecutor的使用及拒绝策略


一、ThreadPoolExecutor介绍

1. 为什么要用线程池?

    过于频繁的创建/销毁线程,会影响处理效率和运行速度,消耗系统资源,降低系统稳定性,一不小心搞崩公司系统直接下岗,而使用线程池可以避免这些问题,稳住饭碗,并且可以对线程这个稀缺资源进行管理、调优与监控

       

                ThreadPoolExecutor的构造函数 ThreadPoolExecutor的构造函数

2. ThreadPoolExecutor构造函数的核心参数

  corePoolSzie: 线程核心池所能容纳的线程数,满后仍有任务进入则进入阻塞队列等待

  maximumPoolSize: 线程池最多所能容纳的线程数,阻塞队列也满后,仍有任务进入,会新建线程(非核心线程)来执行任务,核心池线程数+新建线程数不得超过此参数数值,否则会触发拒绝策略拒绝任务。即新建的非核心线程数最大值 = maximumPoolSize - corePoolSize

  keepAliveTime: 非核心线程若超过此参数指定时间没有任务执行,则销毁线程
  TimeUnit unit: 上个参数的时间单位,TimeUnit是枚举类型,有七种参数:
    NANOSECONDS : 1微毫秒 = 1秒 / 1000 * 1000 * 1000
    MICROSECONDS : 1微秒 = 1秒 / 1000 * 1000
    MILLISECONDS : 1毫秒 = 1秒 /1000
    SECONDS : 秒
    MINUTES : 分
    HOURS : 小时
    DAYS : 天

  BlockingQueue<Runnable> workQueue: 阻塞队列,常用workQueue类型:
    SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大
    LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
    ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
    DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
    threadFactory:用于创建工作线程的工厂。
    handler:拒绝策略,往线程池添加任务时,将在下面两种情况触发拒绝策略:1)线程池运行状态不是 RUNNING;2)线程池已经达到最大线程数,并且阻塞队列已满时。

3. 线程池运行流程

在这里插入图片描述

4. 创建线程池实例

代码如下:

//创建核心线程池; 核心池容量=3; 最大线程数=10; 阻塞队列类型为ArrayBlockingQueue,容量=5; KeepAliveTime = 10ms
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 10L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5));

二、如何使用线程池

1.创建线程

代码如下:

public class MyThread implements Runnable{
   
    //region 构造器

    /**
     * @param flag 线程编号
     * @param currentBlockingQueueSize 当前阻塞队列等待的线程数量
     */
    public MyThread(int flag, int currentBlockingQueueSize) {
   
        this.flag = flag;
        this.currentBlockingQueueSize = currentBlockingQueueSize;
    }
    //endregion

    //region 变量
    private int flag;
    private int currentBlockingQueueSize;
    //endregion


    //region run函数重写

    @Override
    //线程运行
    public void run() {
   
        System.out
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值