线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式
/*1、corePoolSize线程池的常驻核心线程数
2、maximumPoolSize能容纳的最大线程数,线程池中能够容纳同时执行的最大线程数,此值必须大于等于1
3、keepAliveTime空闲线程存活时间,多余的空闲线程存活时间,当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁直到剩下corePoolSize个线程为止
4、unit 存活的时间单位,keepAliveTime单位
5、workQueue 存放提交但未执行任务的队列,被提交但尚未被执行的任务
6、threadFactory 创建线程的工厂类,用于创建线程,一般默认即可
7、handler 等待队列满后的拒绝策略,表示当队列满了,并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝请求执行的runnable的策略*/
ExecutorService newCacheThreadPool = new ThreadPoolExecutor(2, 5,
1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
阿里巴巴Java开发手册明确表示不允许使用Executors去创建线程池,而是通过ThreadPoolExecutor方式创建,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors返回的线程池对象的弊端如下:
1) FixedThreadPool和SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。(out of memory)
2)CachedThreadPool和ScheduledThreadPool:
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM.
拒绝策略JDK默认提供了4种:
AbortPolicy(默认):直接抛出RejectedExecutionException异常组织系统正常运行
CallerRunPolicy: "调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务五回退到调用者,从而降低新任务的流量。就是回退,谁启用的这个线程,就回退到哪,让调用者执行这个线程。
DiscardOldestPolicy: 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
DiscardPolicy: 该策略默默的丢弃无法处理的任务,不予任何处理也不抛出异常,如果允许任务丢失,这是最好的一种策略。