线程池中的核心参数
int corePoolSize:核心线程数,即使线程池中无任务执行,也会创建该数量的线程。
int maximumPoolSize:最大线程数,当核心线程数不够,且队列已满的情况下,会另外创建线程执行任务。
long keepAliveTime:当线程池中的线程处于空闲状态,超过KeepAliveTime时间,则销毁该线程,保持运行的线程数=核心线程数。
BlockingQueue workQueue:任务队列,当任务大于核心线程数,任务会加到队列中等待执行
RejectedExecutionHandler defaultHandler:拒绝策略,详情参考
线程池中四种拒绝策略
下面是线程池的使用以及验证参数
设置核心线程数2,最大线程数7,空闲时存活时间8秒,队列容量3,设置10个线程任务,放入线程池中,为了造成线程数堆积,让任务睡眠5秒。当核心线程数有任务执行,则将新任务加入队列,当任务队列满了,则扩大线程至最大线程数。
public class ThreadPool {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(3);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor
(2, 7, 8, TimeUnit.SECONDS, blockingQueue, new ThreadPoolExecutor.DiscardPolicy());
for(int i = 0; i < 10; i++) {
threadPoolExecutor.execute(
new Thread(){
@Override
public void run() {
try{
System.out.println(Thread.currentThread().getName()+" start");
//体现线程数满的场景,让任务在此处停留,造成线程堆积
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + " end");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
}
//验证KeepAlive,当空闲线程超过KeepAliveTime=8秒,则将线程数降低至核心线程
Thread.sleep(30000);
System.out.println("休息了30s...");
for(int i = 0; i < 5; i++) {
threadPoolExecutor.execute(
new Thread(){
@Override
public void run() {
try{
System.out.println(Thread.currentThread().getName()+" start");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + " end");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
}
}
}
执行结果,可以发现起了7个线程执行任务,因为堆积的任务数超过核心数+队列容量,则扩大至最大线程数7。中间休息的30秒,为了验证空闲时线程数是否会降低至核心线程数,观察运行结果,可以发现保留了两个线程数执行任务。
pool-1-thread-1 start
pool-1-thread-2 start
pool-1-thread-3 start
pool-1-thread-4 start
pool-1-thread-5 start
pool-1-thread-6 start
pool-1-thread-7 start
pool-1-thread-2 end
pool-1-thread-3 end
pool-1-thread-2 start
pool-1-thread-1 end
pool-1-thread-3 start
pool-1-thread-1 start
pool-1-thread-6 end
pool-1-thread-4 end
pool-1-thread-7 end
pool-1-thread-5 end
pool-1-thread-2 end
pool-1-thread-1 end
pool-1-thread-3 end
休息了30s...
pool-1-thread-3 start
pool-1-thread-1 start
pool-1-thread-1 end
pool-1-thread-1 start
pool-1-thread-3 end
pool-1-thread-3 start
pool-1-thread-3 end
pool-1-thread-3 start
pool-1-thread-1 end
pool-1-thread-3 end
部分源码:
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.
*/
int c = ctl.get();
//运行的线程数小于核心线程数,则加入任务线程,
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//如果加入队列成功,进行两次检查能否加入
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);
}
//执行到此处,说明核心线程数和队列都满了,则需创建新线程执行,
//如果创建新线程失败,则执行拒绝策略
else if (!addWorker(command, false))
reject(command);
}