线程池源码分析 (4)

完成上述过程后将线程池状态改为 TIDYING

public void shutdown() { final ReentrantLock mainLock = this.mainLock; // 加锁 mainLock.lock(); try { checkShutdownAccess(); // 改变当前线程池状态 advanceRunState(SHUTDOWN); // 中断当前线程 interruptIdleWorkers(); // 钩子函数,默认空实现 onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }

其中,interruptIdleWorkers()方法如下:

private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 遍历工作队列中的全部 Worker for (Worker w : workers) { Thread t = w.thread; if (!t.isInterrupted() && w.tryLock()) { try { // 标记为中断 t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } } 2.shutdownNow

shutdownNow() 与 shutdown()流程类似,但是会直接将状态转为 STOP,在 addWorker() 或者getTask()等处理任务的相关方法里,会针对 STOP 或更进一步的状态做区分,将不会再处理任务队列中的任务,配合drainQueue()方法以删除任务队列中的任务。

public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 改变当前线程池状态 advanceRunState(STOP); // 中断当前线程 interruptWorkers(); // 删除任务队列中的任务 tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; } 五、拒绝策略

当任务队列已满,并且线程池中线程也到达最大线程数的时候,就会调用拒绝策略。也就是reject()方法

final void reject(Runnable command) { handler.rejectedExecution(command, this); }

拒绝策略共分四种:

AbortPolicy:拒绝策略,直接抛出异常,默认策略;

CallerRunsPolicy:调用者运行策略,用调用者所在的线程来执行任务;

DiscardOldestPolicy:弃老策略,无声无息的丢弃阻塞队列中靠最前的任务,并执行当前任务;

DiscardPolicy:丢弃策略,直接无声无息的丢弃任务;

我们可以简单的了解一下他们的实现:

AbortPolicy

throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());

CallerRunsPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } }

DiscardOldestPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { // 弹出队头元素 e.getQueue().poll(); e.execute(r); } }

DiscardPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { // Does nothing } 六、线程池的钩子函数

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdwgg.html