前置说明
所有的源码基于JDK11.0.2
如何使用线程池呢?
public class WeChatBlogDemos {
@Test
public void useThreadPool ( ) throws InterruptedException {
ExecutorService executorService = Executors . newFixedThreadPool ( 4 ) ;
executorService. submit ( ( ) -> System . out. println ( "hello world" ) ) ;
executorService. shutdown ( ) ;
executorService. awaitTermination ( 2 , TimeUnit . SECONDS) ;
}
}
为什么使用线程池呢?
1)每个Java线程都会对应一个操作系统的工作线程,频繁的创建和销毁线程会有很大的开销,线程池能提高线程的复用率,避免线程频繁的创建和销毁,
2)线程池空闲时能自动缩小容量,防止消耗过多的系统资源,避免资源浪费。
当我往线程池里提交一个任务时,发生了什么【ThreadPoolExecutor.execute】?
1)外部系统通过 shutdown 或 shutdownNow 显式触发了线程池的关闭流程,任务提交失败
2)线程池处于 RUNNING 状态
1)线程池的工作线程数 < 核心线程数,则新增工作者线程进行任务处理
2)线程池的工作线程数 = 核心线程数,往任务队列里提交成功
3)核心线程数 <= 线程池的工作线程数 < 最大线程数 && 往任务队列里提交失败,则新增工作者线程进行任务处理
4)线程池的工作线程数 = 最大线程数 && 往任务队列里提交失败,通过拒绝策略处理任务
public class ThreadPoolExecutor extends AbstractExecutorService {
private volatile ThreadFactory threadFactory;
private volatile RejectedExecutionHandler handler;
private volatile long keepAliveTime;
private volatile boolean allowCoreThreadTimeOut;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy ( ) ;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
private final BlockingQueue < Runnable > workQueue;
private final ReentrantLock mainLock = new ReentrantLock ( ) ;
private final HashSet < Worker > workers = new HashSet < > ( ) ;
private int largestPoolSize;
@Override
public void execute ( Runnable command) {
if ( command == null ) {
throw new NullPointerException ( ) ;
}
int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . workerCountOf ( c) < corePoolSize) {
if ( addWorker ( command, true ) ) {
return ;
}
c = ctl. get ( ) ;
}
if ( ThreadPoolExecutor . isRunning ( c) && workQueue. offer ( command) ) {
final int recheck = ctl. get ( ) ;
if ( ! ThreadPoolExecutor . isRunning ( recheck) && remove ( command) ) {
reject ( command) ;
} else if ( ThreadPoolExecutor . workerCountOf ( recheck) == 0 ) {
addWorker ( null , false ) ;
}
}
else if ( ! addWorker ( command, false ) ) {
reject ( command) ;
}
}
private static int workerCountOf ( int c) { return c & ThreadPoolExecutor . COUNT_MASK; }
private boolean addWorker ( Runnable firstTask, boolean core) {
retry:
for ( int c = ctl. get ( ) ; ; ) {
if ( ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . SHUTDOWN)
&& ( ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . STOP)
|| firstTask != null
|| workQueue. isEmpty ( ) ) ) {
return false ;
}
for ( ; ; ) {
if ( ThreadPoolExecutor . workerCountOf ( c)
>= ( ( core ? corePoolSize : maximumPoolSize) & ThreadPoolExecutor . COUNT_MASK) ) {
return false ;
}
if ( compareAndIncrementWorkerCount ( c) ) {
break retry;
}
c = ctl. get ( ) ;
if ( ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . SHUTDOWN) ) {
continue retry;
}
}
}
boolean workerAdded = false ;
boolean workerStarted = false ;
Worker w = null ;
try {
w = new Worker ( firstTask) ;
final Thread t = w. thread;
if ( t != null ) {
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
final int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . isRunning ( c) ||
ThreadPoolExecutor . runStateLessThan ( c, ThreadPoolExecutor . STOP) && firstTask == null ) {
if ( t. isAlive ( ) ) {
throw new IllegalThreadStateException ( ) ;
}
workers. add ( w) ;
final int s = workers. size ( ) ;
if ( s > largestPoolSize) {
largestPoolSize = s;
}
workerAdded = true ;
}
} finally {
mainLock. unlock ( ) ;
}
if ( workerAdded) {
t. start ( ) ;
workerStarted = true ;
}
}
} finally {
if ( ! workerStarted) {
addWorkerFailed ( w) ;
}
}
return workerStarted;
}
private static boolean runStateAtLeast ( int c, int s) {
return c >= s;
}
private boolean compareAndIncrementWorkerCount ( int expect) {
return ctl. compareAndSet ( expect, expect + 1 ) ;
}
private static boolean isRunning ( int c) {
return c < ThreadPoolExecutor . SHUTDOWN;
}
private static boolean runStateLessThan ( int c, int s) {
return c < s;
}
private void addWorkerFailed ( Worker w) {
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
if ( w != null ) {
workers. remove ( w) ;
}
decrementWorkerCount ( ) ;
tryTerminate ( ) ;
} finally {
mainLock. unlock ( ) ;
}
}
private void decrementWorkerCount ( ) {
ctl. addAndGet ( - 1 ) ;
}
public boolean remove ( Runnable task) {
final boolean removed = workQueue. remove ( task) ;
tryTerminate ( ) ;
return removed;
}
final void reject ( Runnable command) {
handler. rejectedExecution ( command, this ) ;
}
}
工作者线程是如何工作的呢?
1)如果初始化任务不为空,则先执行它
2)从任务队列中循环拉取任务
1)允许当前工作者线程超时退出:则通过 workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) 方式尝试在 keepAliveTime 纳秒内获取任务
2)当前工作者线程数 <= corePoolSize 并且不允许超时退出:通过 workQueue.take() 阻塞读取任务
3)如果拉取到了任务,则执行它,并循环步骤2
4)任务拉取失败、阻塞时被中断、任务执行一次,则执行工作者退出流程。
public class ThreadPoolExecutor extends AbstractExecutorService {
final void runWorker ( Worker w) {
final Thread wt = Thread . currentThread ( ) ;
Runnable task = w. firstTask;
w. firstTask = null ;
w. unlock ( ) ;
boolean completedAbruptly = true ;
try {
while ( task != null || ( task = getTask ( ) ) != null ) {
w. lock ( ) ;
if ( ( ThreadPoolExecutor . runStateAtLeast ( ctl. get ( ) , ThreadPoolExecutor . STOP) ||
Thread . interrupted ( ) &&
ThreadPoolExecutor . runStateAtLeast ( ctl. get ( ) , ThreadPoolExecutor . STOP) ) &&
! wt. isInterrupted ( ) ) {
wt. interrupt ( ) ;
}
try {
beforeExecute ( wt, task) ;
try {
task. run ( ) ;
afterExecute ( task, null ) ;
} catch ( final Throwable ex) {
afterExecute ( task, ex) ;
throw ex;
}
} finally {
task = null ;
w. completedTasks++ ;
w. unlock ( ) ;
}
}
completedAbruptly = false ;
} finally {
processWorkerExit ( w, completedAbruptly) ;
}
}
private Runnable getTask ( ) {
boolean timedOut = false ;
for ( ; ; ) {
final int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . SHUTDOWN)
&& ( ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . STOP) || workQueue. isEmpty ( ) ) ) {
decrementWorkerCount ( ) ;
return null ;
}
final int wc = ThreadPoolExecutor . workerCountOf ( c) ;
final boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ( ( wc > maximumPoolSize || timed && timedOut)
&& ( wc > 1 || workQueue. isEmpty ( ) ) ) {
if ( compareAndDecrementWorkerCount ( c) ) {
return null ;
}
continue ;
}
try {
final Runnable r = timed ?
workQueue. poll ( keepAliveTime, TimeUnit . NANOSECONDS) :
workQueue. take ( ) ;
if ( r != null ) {
return r;
}
timedOut = true ;
} catch ( final InterruptedException retry) {
timedOut = false ;
}
}
}
protected void beforeExecute ( Thread t, Runnable r) {
}
protected void afterExecute ( Runnable r, Throwable t) {
}
private void processWorkerExit ( Worker w, boolean completedAbruptly) {
if ( completedAbruptly) {
decrementWorkerCount ( ) ;
}
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
completedTaskCount += w. completedTasks;
workers. remove ( w) ;
} finally {
mainLock. unlock ( ) ;
}
tryTerminate ( ) ;
final int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . runStateLessThan ( c, ThreadPoolExecutor . STOP) ) {
if ( ! completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if ( min == 0 && ! workQueue. isEmpty ( ) ) {
min = 1 ;
}
if ( ThreadPoolExecutor . workerCountOf ( c) >= min) {
return ;
}
}
addWorker ( null , false ) ;
}
}
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable {
private static final long serialVersionUID = 6138294804551838833L ;
final Thread thread;
Runnable firstTask;
volatile long completedTasks;
Worker ( Runnable firstTask) {
setState ( - 1 ) ;
this . firstTask = firstTask;
thread = getThreadFactory ( ) . newThread ( this ) ;
}
@Override
public void run ( ) {
runWorker ( this ) ;
}
}
}
如何停止线程池呢?
触发线程池关闭之后,提交到线程池的任务会被直接拒绝
1)通过 shutdown 停止线程池时,线程池的状态会递进到 SHUTDOWN,并且活跃工作者线程还能处理剩余任务。
2)通过 shutdownNow 停止线程池时,线程池的状态会递进到 STOP,并且活跃工作者线程不能处理剩余任务,拉取到的任务是 null。
public class ThreadPoolExecutor extends AbstractExecutorService {
@Override
public void shutdown ( ) {
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
checkShutdownAccess ( ) ;
advanceRunState ( ThreadPoolExecutor . SHUTDOWN) ;
interruptIdleWorkers ( ) ;
onShutdown ( ) ;
} finally {
mainLock. unlock ( ) ;
}
tryTerminate ( ) ;
}
private void checkShutdownAccess ( ) {
final SecurityManager security = System . getSecurityManager ( ) ;
if ( security != null ) {
security. checkPermission ( ThreadPoolExecutor . shutdownPerm) ;
for ( final Worker w : workers) {
security. checkAccess ( w. thread) ;
}
}
}
private void advanceRunState ( int targetState) {
for ( ; ; ) {
final int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . runStateAtLeast ( c, targetState) ||
ctl. compareAndSet ( c, ThreadPoolExecutor . ctlOf ( targetState, ThreadPoolExecutor . workerCountOf ( c) ) ) ) {
break ;
}
}
}
private void interruptIdleWorkers ( ) {
interruptIdleWorkers ( false ) ;
}
private void interruptIdleWorkers ( boolean atMostOne) {
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
for ( final Worker w : workers) {
final Thread t = w. thread;
if ( ! t. isInterrupted ( ) && w. tryLock ( ) ) {
try {
t. interrupt ( ) ;
} catch ( final SecurityException ignore) {
} finally {
w. unlock ( ) ;
}
}
if ( atMostOne) {
break ;
}
}
} finally {
mainLock. unlock ( ) ;
}
}
void onShutdown ( ) {
}
final void tryTerminate ( ) {
for ( ; ; ) {
final int c = ctl. get ( ) ;
if ( ThreadPoolExecutor . isRunning ( c) ||
ThreadPoolExecutor . runStateAtLeast ( c, ThreadPoolExecutor . TIDYING) ||
ThreadPoolExecutor . runStateLessThan ( c, ThreadPoolExecutor . STOP) && ! workQueue. isEmpty ( ) ) {
return ;
}
if ( ThreadPoolExecutor . workerCountOf ( c) != 0 ) {
interruptIdleWorkers ( ThreadPoolExecutor . ONLY_ONE) ;
return ;
}
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
if ( ctl. compareAndSet ( c, ThreadPoolExecutor . ctlOf ( ThreadPoolExecutor . TIDYING, 0 ) ) ) {
try {
terminated ( ) ;
} finally {
ctl. set ( ThreadPoolExecutor . ctlOf ( ThreadPoolExecutor . TERMINATED, 0 ) ) ;
termination. signalAll ( ) ;
}
return ;
}
} finally {
mainLock. unlock ( ) ;
}
}
}
protected void terminated ( ) {
}
@Override
public List < Runnable > shutdownNow ( ) {
List < Runnable > tasks;
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
checkShutdownAccess ( ) ;
advanceRunState ( ThreadPoolExecutor . STOP) ;
interruptWorkers ( ) ;
tasks = drainQueue ( ) ;
} finally {
mainLock. unlock ( ) ;
}
tryTerminate ( ) ;
return tasks;
}
private List < Runnable > drainQueue ( ) {
final BlockingQueue < Runnable > q = workQueue;
final ArrayList < Runnable > taskList = new ArrayList < > ( ) ;
q. drainTo ( taskList) ;
if ( ! q. isEmpty ( ) ) {
for ( final Runnable r : q. toArray ( new Runnable [ 0 ] ) ) {
if ( q. remove ( r) ) {
taskList. add ( r) ;
}
}
}
return taskList;
}
}
等待线程池完全退出
目标线程会最多阻塞 unit.toNanos(timeout) 时间来等待线程池完全销毁。
public class ThreadPoolExecutor extends AbstractExecutorService {
@Override
public boolean awaitTermination ( long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit. toNanos ( timeout) ;
final ReentrantLock mainLock = this . mainLock;
mainLock. lock ( ) ;
try {
while ( ThreadPoolExecutor . runStateLessThan ( ctl. get ( ) , ThreadPoolExecutor . TERMINATED) ) {
if ( nanos <= 0L ) {
return false ;
}
nanos = termination. awaitNanos ( nanos) ;
}
return true ;
} finally {
mainLock. unlock ( ) ;
}
}
}
线程池的逻辑最大线程数是多少呢?
线程池的线程数保存在 ctl 控制变量的低 29 位中,因此线程池的逻辑最大线程数为 2^29-1。
public class ThreadPoolExecutor extends AbstractExecutorService {
private final AtomicInteger ctl = new AtomicInteger ( ThreadPoolExecutor . ctlOf ( ThreadPoolExecutor . RUNNING, 0 ) ) ;
private static final int COUNT_BITS = Integer . SIZE - 3 ;
private static final int COUNT_MASK = ( 1 << COUNT_BITS) - 1 ;
private static int workerCountOf ( int c) { return c & ThreadPoolExecutor . COUNT_MASK; }
}
线程池内置了哪些拒绝策略呢?
1)CallerRunsPolicy:线程池未关闭,则交给提交任务的线程自己执行
2)AbortPolicy:抛出 RejectedExecutionException 异常,默认拒绝策略。
3)DiscardPolicy:静默丢弃
4)DiscardOldestPolicy:静默丢弃最老的任务后,重新提交到线程池
public class ThreadPoolExecutor extends AbstractExecutorService {
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy ( ) { }
@Override
public void rejectedExecution ( Runnable r, ThreadPoolExecutor e) {
if ( ! e. isShutdown ( ) ) {
r. run ( ) ;
}
}
}
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy ( ) { }
@Override
public void rejectedExecution ( Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException ( "Task " + r. toString ( ) +
" rejected from " +
e. toString ( ) ) ;
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy ( ) { }
@Override
public void rejectedExecution ( Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy ( ) { }
@Override
public void rejectedExecution ( Runnable r, ThreadPoolExecutor e) {
if ( ! e. isShutdown ( ) ) {
e. getQueue ( ) . poll ( ) ;
e. execute ( r) ;
}
}
}
}
内置线程池有哪些?
1)newFixedThreadPool:固定工作者线程池
2)newCachedThreadPool:一个任务一个工作者线程池,无法存储任务
3)newSingleThreadExecutor:单工作者线程池
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
}
线程池有哪几种运行状态呢?
线程池有 5 种运行状态,状态值是顺序递增的,分别为 RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。
RUNNING: 接受新任务,同时处理工作队列中的任务
SHUTDOWN: 不接受新任务,但是能处理工作队列中的任务
STOP: 不接受新任务,不处理工作队列中的任务,并且强制中断正在运行的工作者线程
TIDYING: 所有的工作者线程都已经停止,将运行 terminated() 钩子函数
TERMINATED: terminated() 钩子函数运行完毕,线程池退出
RUNNING -> SHUTDOWN【调用 shutdown 时触发状态流转】
RUNNING -> STOP【调用 shutdownNow 时触发状态流转】
SHUTDOWN -> TIDYING【队列和线程池都为空时】
STOP -> TIDYING【队列和线程池都为空时】
TIDYING -> TERMINATED【terminated 方法完成执行时】
public class ThreadPoolExecutor extends AbstractExecutorService {
private static final int RUNNING = - 1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
}
什么情况下线程池的所有工作者线程都会退出?
allowCoreThreadTimeOut=true && workQueue.isEmpty()
工作者线程拉取任务时被中断了会发生什么?
会继续拉取任务?
线程池停止过程中会中断空闲工作者线程,如何保证不会伤及运行中的工作者线程?
工作者线程本身继承了 AbstractQueuedSynchronizer,是一个互斥锁,当其获取到任务时会对自己进行锁定,
线程池中断空闲线程过程中由于无法获取锁,此工作者线程不会被中断。
shutdown 和 shutdownNow 的区别是什么?
1)shutdown 之后:线程池的工作线程能完成正在处理的任务,也能拉取到存留的任务,任务队列中的任务会被执行完毕。
2)shutdownNow 之后:线程池的工作线程只能完成正在处理的任务,但是无法拉取到存留的任务,存留任务会通过方法返回。
使用线程池的最佳实践
1)自定义 ThreadFactory 并在其创建线程时提供一个有效的名称,用于后续的跟踪分析。
2)限定任务队列的长度,避免突发流量导致系统 OOM。
3)线程池创建完毕可以通过预先启动工作者线程来缩短响应时间
prestartCoreThread:预先启动一个工作者线程
prestartAllCoreThreads:预先启动所有的核心工作者线程