线程池创建中核心参数关系源码解读
核心参数
- 核心线程数(corePoolSize)
业务线程数安装CPU密集型1N,IO密集型2N,多了会抢占资源 (Nlinux服务CPU核大小)
- 最大线程数(maximumPoolSize)
业务线程数安装CPU密集型1N,IO密集型2N,多了会抢占资源 (Nlinux服务CPU核大小)
- 空闲线程的保活时间(keepAliveTime)
多出的核心线程的空闲线程存活时间
- 任务队列(workQueue)
BlockingQueue 接口的某个实现(常使用 ArrayBlockingQueue 和 LinkedBlockingQueue)
- 拒绝策略defaultHandler
默认:丢弃任务并抛出RejectedExecutionException异常,
RejectedExecutionHandler defaultHandler = new AbortPolicy(),一共四种策略
参数关系源码解读
ThreadPoolExecutor#execute方法创建线程
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private final BlockingQueue<Runnable> workQueue;
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
上面的英文翻译
* 1。如果运行的线程少于corePoolSize,请尝试以给定的命令作为第一个线程启动一个新线程任务。对addWorker的调用会自动检查runState和
* workerCount,因此可以防止添加的假警报线程当它不应该,通过返回false。
* 2。如果一个任务可以成功地排队,那么我们仍然需要再次检查是否应该添加线程(因为上次检查后现有的已经死了)或那样进入该方法后,池关闭。所以我们
*重新检查状态,并在必要时回滚登记停止,如果没有,则启动一个新线程。
* 3。如果我们不能对任务进行排队,那么我们尝试添加一个新的线程。如果它失败了,我们知道我们被关闭或饱和因此,拒绝这个任务。
*/
int c = ctl.get();
//1:如果目前运行的线程小于核心线程, addWorker创建线程,true同时把改创建的线程标记为核心线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//2: isRunning(c)当前的线程是否都在运行 ,新来线程添加阻塞队列中
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//3:如果阻塞队列已满,则再创建线程,同时把改创建的线程标记为非核心线程
else if (!addWorker(command, false))
//4:如果不能再创建线程,则把新加入的线程添加到拒绝策略中 目前运行的线程大于(核心线程数+阻塞队列数)则不能创建
reject(command);
}
四创建线程池类
- 四类程序:newFixedThreadPool newSingleThreadExecutor newCachedThreadPool newScheduledThreadPool
注意:1:newFixedThreadPool (坑1:LinkedBlockingQueue的队列默认值数很大,会导致OOM) 2:newCachedThreadPool (坑1:线程数默认值,会导致OOM)