【高并发】深度解析ScheduledThreadPoolExecutor类的源代码

在【高并发专题】的专栏中,我们深度分析了ThreadPoolExecutor类的源代码,而ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类 。今天我们就来一起手撕ScheduledThreadPoolExecutor类的源代码 。
构造方法我们先来看下ScheduledThreadPoolExecutor的构造方法,源代码如下所示 。
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory);}public ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), handler);}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory, handler);}从代码结构上来看,ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类,ScheduledThreadPoolExecutor类的构造方法实际上调用的是ThreadPoolExecutor类的构造方法 。
schedule方法接下来,我们看一下ScheduledThreadPoolExecutor类的schedule方法,源代码如下所示 。
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { //如果传递的Runnable对象和TimeUnit时间单位为空 //抛出空指针异常 if (command == null || unit == null)throw new NullPointerException(); //封装任务对象,在decorateTask方法中直接返回ScheduledFutureTask对象 RunnableScheduledFuture<?> t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); //执行延时任务 delayedExecute(t); //返回任务 return t;}public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) //如果传递的Callable对象和TimeUnit时间单位为空 //抛出空指针异常 if (callable == null || unit == null)throw new NullPointerException(); //封装任务对象,在decorateTask方法中直接返回ScheduledFutureTask对象 RunnableScheduledFuture<V> t = decorateTask(callable,new ScheduledFutureTask<V>(callable, triggerTime(delay, unit))); //执行延时任务 delayedExecute(t); //返回任务 return t;}从源代码可以看出,ScheduledThreadPoolExecutor类提供了两个重载的schedule方法,两个schedule方法的第一个参数不同 。可以传递Runnable接口对象,也可以传递Callable接口对象 。在方法内部,会将Runnable接口对象和Callable接口对象封装成RunnableScheduledFuture对象,本质上就是封装成ScheduledFutureTask对象 。并通过delayedExecute方法来执行延时任务 。
在源代码中,我们看到两个schedule都调用了decorateTask方法,接下来,我们就看看decorateTask方法 。
decorateTask方法decorateTask方法源代码如下所示 。
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) { return task;}protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) { return task;}通过源码可以看出decorateTask方法的实现比较简单,接收一个Runnable接口对象或者Callable接口对象和封装的RunnableScheduledFuture任务,两个方法都是将RunnableScheduledFuture任务直接返回 。在ScheduledThreadPoolExecutor类的子类中可以重写这两个方法 。
接下来,我们继续看下scheduleAtFixedRate方法 。
scheduleAtFixedRate方法scheduleAtFixedRate方法源代码如下所示 。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { //传入的Runnable对象和TimeUnit为空,则抛出空指针异常 if (command == null || unit == null)throw new NullPointerException(); //如果执行周期period传入的数值小于或者等于0 //抛出非法参数异常 if (period <= 0)throw new IllegalArgumentException(); //将Runnable对象封装成ScheduledFutureTask任务,//并设置执行周期 ScheduledFutureTask<Void> sft =new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period)); //调用decorateTask方法,本质上还是直接返回ScheduledFutureTask对象 RunnableScheduledFuture<Void> t = decorateTask(command, sft); //设置执行的任务 sft.outerTask = t; //执行延时任务 delayedExecute(t); //返回执行的任务 return t;}

经验总结扩展阅读