线程池ThreadPoolExecutor
详解
内置四种构造器,但最终重载的是下面的构造函数
1 2
| ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit ,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
|
构造函数的参数说明
corePoolSize
maximumPoolSize
- 池子的最大线程数,是指最大正在运行中的数量;当核心线程和阻塞队列都满了,若此时有新的线程过来,则会创建线程
keepAliveTime
unit
workQueue
- 线程排队等待的阻塞队列,当核心线程都满了,此时若有新的线程过来,则会在这个队列中排队
threadFactory
handler
- 拒绝策略,当核心线程满了,阻塞队列也满了,运行中的线程数量也达到最大数,此时若有线程进来,则会根据该策略进行拒绝服务
- 默认提供有四种拒绝策略:
CallerRunsPolicy
由调用者执行新的线程
AbortPolicy
直接拒绝并抛异常(默认策略)
DiscardPolicy
直接丢弃新线程
DiscardOldestPolicy
丢弃最旧的线程(最先提交而没有得到执行的任务)
corePoolSize
、maximumPoolSize
、workQueue
三者之间的关系
1.若无空闲线程执行该任务且当前运行中线程数少于corePoolSize
,则直接创建新线程执行该任务。
2.若无空闲线程执行该任务且当前运行中线程数等于corePoolSize
且阻塞队列未满,则将任务入队列等待,而不创建新线程
3.若无空闲线程执行该任务且阻塞队列已满同时池中的线程数小于maximumPoolSize
,则创建新线程执行该任务
4.若无空闲线程执行该任务且阻塞队列已满同时池中的线程数等于maximumPoolSize
,则根据构造函数中的handler
指定的策略来拒绝新的任务
ThreadPoolExecutor扩展
ThreadPoolExecutor扩展主要是围绕beforeExecute()
、afterExecute()
和terminated()
三个接口实现的,
- beforeExecute:线程池中任务运行前执行
- afterExecute:线程池中任务运行完毕后执行
- terminated:线程池退出后执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ExecutorService pool = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5) , (runnable)-> new Thread(runnable, "threadPool" + runnable.hashCode()) , new ThreadPoolExecutor.CallerRunsPolicy()) { @Override protected void beforeExecute(Thread t, Runnable r) { System.out.println("准备执行:" + t.getName()); } @Override protected void afterExecute(Runnable r, Throwable t) { System.out.println("执行完毕:" + t.getMessage()); } @Override protected void terminated() { System.out.println("线程池退出"); } };
|
工作原理
主要参数说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| private static final int RUNNING = -1 << 29 ;
private static final int SHUTDOWN = 0 << 29 ;
private static final int STOP = 1 << 29 ;
private static final int TIDYING = 2 << 29 ;
private static final int TERMINATED = 3 << 29 ;
private final BlockingQueue<Runnable> workQueue;
private final ReentrantLock mainLock = new ReentrantLock();
private final HashSet<Worker> workers = new HashSet<Worker>();
private final Condition termination = mainLock.newCondition();
private int largestPoolSize;
private long completedTaskCount;
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();
|
核心方法submit
1 2 3 4 5 6
| public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; }
|
其中newTaskFor
是用来包装传入的任务,注意入口方法execute
如期而至,下面我们就一点点揭开它那神秘的面纱以观其美妙的。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public void execute(Runnable command) { if (command == null) throw new NullPointerException(); 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); }
|
待揭开后发现还是未能触那美好的。。。别急,继续揭开核心方法addWorker(Runnable firstTask, boolean core)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()) ) return false; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); if (runStateOf(c) != rs) continue retry; } } boolean workerStarted = false; boolean workerAdded = 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 { int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) throw new IllegalThreadStateException(); workers.add(w); 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; }
|
继续分析Worker
中的runWorker
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| final void runWorker(Worker w) { 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 ((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); } }
|
线程中断wt
;
- 如果线程池处于
STOP
,TIDYING
,TERMINATED
状态并且wt
没有被中断,则中断 wr
。
- 如果当前线程被中断了并且线程池处于
STOP
,TIDYING
,TERMINATED
状态并且wt
没有被中断,则中断 wr
getTask()
从队列得到一个task
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
private Runnable getTask() { boolean timedOut = false; for (;;) { int c = ctl.get(); int rs = runStateOf(c); if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS):workQueue.take(); if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }
|