ExecutorService详细介绍(ThreadPoolExecutor)

ExecutorService详细介绍(ThreadPoolExecutor)

ExecutorService的主要实现类为ThreadPoolExecutor,网上搜索ExecutorService的使用,很多情况下搜索出来的是通过Executors来进行创建的,但是使用Executors会带来一些问题,阿里java规范文档也明确禁止使用Executors创建线程池(如果想要了解为什么不使用Executors创建线程,请看这篇文章阿里为何禁用Executors创建线程池)。其实Executors底层也是使用ThreadPoolExecutor进行创建的,只是使用Executors可以帮我们少些一些参数,我这里就使用ThreadPoolExecutor直接创建对象,ThreadPoolExecutor的参数如下:

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


corePoolSize 线程池核心数(程序运行的正常线程数量,从0开始增加)
maximumPoolSize 最大线程数(工作队列满了以后,会继续创建线程,直到线程数量大于maximumPoolSize后抛执行错误策略,这里要注意maximumPoolSize要大于corePoolSize,否则抛异常)
keepAliveTime 闲置时间(当线程数大于corePoolSize,且有闲置的线程,则当线程经过了keepAliveTime时间后会被销毁)
unit 用于描述keepAliveTime的
BlockingQueue<Runnable> workQueue 工作队列(当线程数大于corePoolSize时,会进入工作队列进行等待)
ThreadFactory 线程工厂(用于创建线程的工程,一般使用默认的)
RejectedExecutionHandler 错误策略(当线程数超过maximumPoolSize后,该错误策略将被执行)

这里粘贴一下我报的网课老师画的图,方便大家理解这几个参数

 

来一个小Demo来认识一下这些参数的作用,这里的BlockingQueue、RejectedExecutionHandler和ThreadFactory都是使用最简单的,如果想要更深入了解,可以自行百度,后续有时间我再补充。

public class ThreadPoolExecutorTest {

    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(2, //核心线程数为2
                5, //最大线程数为5
                10, TimeUnit.SECONDS, //设置10秒过期
                new LinkedBlockingDeque(2), //队列大小为2
                new MyThreadFactory(),//这里用简单的线程工厂
                new RejectedExecutionHandler() {
                    @Override
                    //错误策略,超过最大线程数后执行该方法
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        System.out.println("ThreadName:" + Thread.currentThread().getName() + "执行拒绝策略:");
                    }
                });
        for (int i = 0; i < 10; i++) {
            Runnable runnable = new MyRunnable();
            executorService.execute(runnable);
            try {
                System.out.println("创建线程:" + i);
                Thread.sleep(1000);//1秒创建一个
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.shutdown();

    }
}


class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r);
    }
}


class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("ThreadName:" + Thread.currentThread().getName() + "线程执行:");
        try {
            Thread.sleep(8000);//每个线程休息8秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出结果为

创建线程:0
ThreadName:Thread-0线程执行:
创建线程:1
ThreadName:Thread-1线程执行:
创建线程:2
创建线程:3
创建线程:4
ThreadName:Thread-2线程执行:
创建线程:5
ThreadName:Thread-3线程执行:
创建线程:6
ThreadName:Thread-4线程执行:
创建线程:7
ThreadName:main执行拒绝策略:
ThreadName:Thread-0线程执行:
创建线程:8
ThreadName:Thread-1线程执行:
创建线程:9
ThreadName:Thread-2线程执行:
ThreadName:Thread-3线程执行:

我们来分析一下结果:

1、核心线程数为2,所以前面两条0、1线程被创建后立马执行了;

2、第2和第3线程创建好后并没有立即执行,而是进入了等待队列;

3、第4、5、6创建后立马执行了,说明队列满了,所以重新创建线程;

4、第7线程执行时候,由于线程已经达到核心线程数了,所以执行了错误策略;

5、第8、9线程,由于runnable里面只停留8秒,所以此时0线程被释放了,但是等待队列也释放了,如果8、9线程抢到执行权,则直接执行,否则进入到等待队列中;

6、最后执行等待队列中的线程,到此整个流程结束;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值