本文共 6747 字,大约阅读时间需要 22 分钟。
由于系统线程池每天需要处理的任务线程不是固定不变的,会多会少,所以线程池存在自己的线程增加方式。当然,线程池的中线程的数量也是应该是有限的,因为过多的线程需要耗费很多的系统资源。
线程池接收到任务线程后的完整操作流程:
线程池构造函数中的接口参数import java.util.concurrent.RejectedExecutionHandler为我提供了线程池拒绝线程任务策略,下图中展示的是import java.util.concurrent.RejectedExecutionHandler结构的实现类,即线程池拒绝线程任务策略的具体实现。
RejectHandler
private static class RejectHandler implements RejectedExecutionHandler { private RejectHandler() { } public void rejectedExecution(Runnable r, java.util.concurrent.ThreadPoolExecutor executor) { //直接抛出异常 throw new RejectedExecutionException(); }}
RejectHandler是接口import java.util.concurrent.RejectedExecutionHandler在Tomcat中实现类。该实现类仅仅是通方法rejectedExecution方法直接抛出拒绝执行异常。
AbortPolicy(线程池默认)
/** * The default rejected execution handler */ private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); /** * A handler for rejected tasks that throws a * {@code RejectedExecutionException}. */ public static class AbortPolicy implements RejectedExecutionHandler { /** * Creates an {@code AbortPolicy}. */ public AbortPolicy() { } /** * Always throws RejectedExecutionException. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task * @throws RejectedExecutionException always */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
该拒绝策略直接通过方法rejectedExecution抛出解决执行异常,r 为执行的请求执行的可执行任务,e为试图执行此任务的执行者,异常信息为可执行任务r为某可执行者e拒绝了。
CallerRunsPolicy
/** * A handler for rejected tasks that runs the rejected task * directly in the calling thread of the {@code execute} method, * unless the executor has been shut down, in which case the task * is discarded. */ public static class CallerRunsPolicy implements RejectedExecutionHandler { /** * Creates a {@code CallerRunsPolicy}. */ public CallerRunsPolicy() { } /** * Executes task r in the caller's thread, unless the executor * has been shut down, in which case the task is discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run();//提交任务的由提交任务的线程自己通过run方法执行 } } }
该拒绝策略不同于上述两种拒绝策略直接拒绝执行而抛出异常,而是先判断线程池是否被停止。如果是没有被停止的情况,就会由任务线程r自己使用run方法执行。通俗的来说,该拒绝策略为当线程池无法处理当前提交的线程任务,同时提交该线程任务的时主线程时,则该任务就会由主线程执行。这样处理可以在避免任务损失的同时,降低了提交任务的速度,从而给线程池一些缓冲的时间。
DiscardPolicy
/** * A handler for rejected tasks that silently discards the * rejected task. */ public static class DiscardPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardPolicy}. */ public DiscardPolicy() { } /** * Does nothing, which has the effect of discarding task r. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
该拒绝策略是一个会悄悄的拒绝任务线程,又不发出任何通知的狠角色,真是人狠话不多。
DiscardOldestPolicy
/** * A handler for rejected tasks that discards the oldest unhandled * request and then retries {@code execute}, unless the executor * is shut down, in which case the task is discarded. */ public static class DiscardOldestPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardOldestPolicy} for the given executor. */ public DiscardOldestPolicy() { } /** * Obtains and ignores the next task that the executor * would otherwise execute, if one is immediately available, * and then retries execution of task r, unless the executor * is shut down, in which case task r is instead discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { //队列是一种先进先出的数据结构,所以队首的任务存活时间最长 e.getQueue().poll(); //丢弃存储队列中存活时间最长的任务线程 e.execute(r);//尝试处理新的任务线程 } } }
getQueue()
//获取存储队列,该队列为阻塞队列 public BlockingQueuegetQueue() { return workQueue; }
execute(Runnable r)
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); //第一步首先检测是否小于核心线程数 if (workerCountOf(c) < corePoolSize) { //增加一个线程,addWorker增加一个工作线程,command即为我们的任务 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); }
execute(Runnable commond)方法执行过程被分为三步:
reject(Runnable command)
public class ThreadPoolExecutor extends AbstractExecutorService { private volatile RejectedExecutionHandler handler; final void reject(Runnable command) { handler.rejectedExecution(command, this); }}
rejectedExecution(Runnable command , ThreadPoolExecutor executor)
public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecutor executor);}
该策略在线程池未停止的情况下,会将存储队列中存储时间最长的任务丢弃,然后重新尝试执行新的非空任务线程,只是使用reject方法来拒绝执行额外的线程。
转载地址:http://ykpiz.baihongyu.com/