如果已有的线程池都不能满足业务的需求,那么就可以通过 ThreadPoolExecutor 来自定义一种类型的线程池。具体地说,可以通过 ThreadPoolExecutor 的构造方法来创建一个自定义的线程池对象,并且通过 execute 向池中提交无返回值的任务(类似于 run() 方法),或者使用 submit() 向池中提交有返回值的任务(同样是用 Future 接收返回值)。
public class ThreadPoolExecutor extends AbstractExecutorService {
// 根据不同的参数个数,一共有4种用于创建 ThreadPoolExecutor 对象的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
his.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
}
线程池中核心线程数的最大值。核心线程是指一旦有任务提交,核心线程就会去执行。
线程池中最多能容纳的线程总数。线程总数 = 核心线程数 + 非核心线程数。非核心线程是指如果有任务提交,任务先交给核心线程去执行,如果核心线程满了再将任务放到 workQueue 中,如果 workQueue 也满了才将任务交给非核心线程去只执行。
线程中非核心线程的最大空闲时长。如果超过了该时间,空闲的非核心线程就会从线程池中被删除。如果设置了 allowCoreThreadTimeOut = true,那么 keepAliveTime 也会作用于核心线程。
keepAliveTime 的时间单位。
等待提交到线程池中的任务队列。如果所有核心线程都在执行,那么新添加的任务就会被增加到这个队列等待处理;如果队列满了,线程池就会创建非核心线程去执行这些无法添加到队列中的任务;如果向线程池中提交的任务数量 > (maximumPoolSize+workQueue.size())时,程序就会抛出异常,异常类型取决于构造方法的最后一个参数 handler。
创建线程的方式。一般不用设置,使用默认值即可。
拒绝策略。当向线程池中提交的任务已满,即向线程池中提交的任务数量 > (maximumPoolSize+workQueue.size())时,如何拒绝超额的任务。拒绝策略的上级接口是 RejectedExecutionHandler,该接口定义了拒绝时执行的方法 rejectedExecution,源码如下。
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
该接口的4个实现类,就是4种拒绝策略。
AbortPolicy:默认拒绝策略,如果 maximumPoolSize+workQueue.size() 已经饱和,就丢掉超额的任务,并抛出 RejectedExecutionHandler 异常。
DiscardPolicy:如果 maximumPoolSize+workQueue.size() 已经饱和,就丢掉超额的任务,但不会抛出异常。
DiscardOldestPolicy:队列是 FIFO 的结构,当采用此策略时,如果已经饱和就删除最早进入队列的任务,再将新任务追加到队尾。
CallerRunsPolicy:如果饱和,新任务不会去尝试添加到 workQueue 中,而是直接去调用 execute(),是一种"急脾气"的策略。
此外,还可以自定义一个实现 RejectedExecutionHandler 接口的类,即自定义拒绝策略。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/chengqiuming/article/details/124652652
内容来源于网络,如有侵权,请联系作者删除!