为什么《阿里巴巴Java开发手册》强制不允许使用Executor创建线程池?

看过《阿里Java开发手册》的你,应该知道

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

上图

1

ThreadPoolExecutor机制
核心构造方法讲解

下面是ThreadPoolExecutor最核心的构造方法参数:
1)corePoolSize 核心线程池的大小
2)maximumPoolSize 最大线程池大小
3)keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程超出有效时间也关闭
4)TimeUnit keepAliveTime的时间单位
5)workQueue阻塞任务队列
6)threadFactory新建线程工厂
7)RejectedExecutionHandler当提交任务数超过maximumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理

重点讲解

corePoolSizemaximumPoolSizeworkQueue三者之间的关系
1)当线程池小于corePoolSize时,新提交的任务会创建一个新线程执行任务,即使线程池中仍有空闲线程。
2)当线程池达到corePoolSize时,新提交的任务将被放在workQueue中,等待线程池中的任务执行完毕
3)当workQueue满了,并且maximumPoolSize > corePoolSize时,新提交任务会创建新的线程执行任务
4)当提交任务数超过maximumPoolSize,新任务就交给RejectedExecutionHandler来处理
5)当线程池中超过 corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
6)当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

2

为什么上面不允许使用Executors工厂类,要自己定义呢?

1)创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池就会补充一个新的线程。
配置的corePoolSizemaximumPoolSize大小相同,同时使用一个无界LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在再阻塞队列,不会由RejectedExecutionHandler来处理。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

2)创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是说相当于单线程串行执行所有任务。如果这个唯一的线程因为异常而结束,那么会新建一个线程来替换。
此线程池保证所有的任务的执行顺序按照任务的提交顺序执行。配置corePoolSize = maximumPoolSize = 1,无界阻塞队列LinkedBlockingQueue;保证任务有一个线程串行执行

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

3)创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒)不执行任务的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
此线程池不会对线程池的大小做限制,线程池的大小完全依赖于操作系统(或者JVM)能够创建的最大线程大小。配置corePoolSize = 0 maximumPoolSize = Integer.MAX_VALUE keepAliveTime = 60s,以及一个无容量的阻塞队列SynchronousQueue,因此任务提交之后,将会创建新的线程执行;线程空闲超过60s就会销毁

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

4)构造有定时功能的线程池,配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue;有意思的是:maximumPoolSize = Integer.MAX_VALUE,由于DelayedWorkQueue是无界的,所以这个值是没有意义的。

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}
我们可以借鉴上面的实现自己的ThreadPoolExecutor
祝进步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值