- 线程池构造参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
corePoolSize 核心线程数
maximumPoolSize 最大工作线程数
keepAliveTime 非核心线程存活时间
unit 非核心线程存活时间keepAliveTime 的时间单位
workQueue 阻塞队列
threadFactory 线程工厂,一般用于设置线程name
handler 拒绝策略,当线程池不能处理更多的任务时会执行这个方法
CallerRunsPolicy 由当前提交任务的线程执行,即执行run方法
AbortPolicy 抛出异常RejectedExecutionHandler
DiscardPolicy 丢弃当前任务,并不会抛出异常
DiscardOldestPolicy 丢弃队列中队首的任务,放入当前任务
- 提交任务方式
pool.submit(()->{
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
pool.execute(()->{
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
submit和execute方法的区别
1.submit 会把任务包装成FutureTask,并可以通过FutureTask.get() 获取到执行结果
2.当出现异常时,execute直接抛出异常,submit则可以通过FutureTask.get 方法捕捉到异常
- execute执行过程
1.首先判断当前工作线程数是否超过核心线程数corePoolSize ;
2.如果没超过,则把任务封装成Worker对象,Worker实现了Runnable接口,可以通过ThreadFactory.newThread创建一个线程,这个线程传入了Worker,并把设置到Worker的thread属性中,并添加到线程池的HashSet workers集合中;这样一来,执行创建的这个线程start方法,就是会执行Worker的run方法,而这方法又会执行他的runWorker()方法,并在这个方法中执行我们传入的任务的run方法
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
private static final long serial
final Thread thread;
Runnable firstTask;
volatile long completedTasks;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
3.runWorker方法是一个while循环的,当前任务执行完后,会将task置位空,再调用getTask方法从阻塞队列中获取新的任务执行
4.如果往线程池中提交任务是,当前核心线程数等于设置corePoolSize,则会将当前任务提交到工作队列中,交由第三步的核心线程通过getTask方法拿到新的任务去执行
5.如果第4步提交任务到阻塞队列中失败,则需要创建非核心工作线程去处理这些任务
6.如果第5步中发现核心线程数+非核心线程数=maximumPoolSize,则会执行拒绝策略中rejectedExecution(Runnable r, ThreadPoolExecutor executor) 方法
7.回收非核心工作线程,会判断当前的线程数是否大于核心线程数,如果大于,则调用阻塞队列的poll方法,并以创建线程池时传入的keepAliveTime设置超时时间。如果此时没有新提交的任务,则会返回null,并结束这个线程。这里并不会区分核心线程还是非核心线程,只要线程数减少到核心线程数就行了
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
8.submit方法,会把任务封装成FutureTask,并调用execute方法提交任务
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}