Java中调度线程池ScheduledThreadPoolExecutor原理探究
来源:互联网 发布:淘宝卖家商品管理软件 编辑:程序博客网 时间:2024/05/15 10:33
类关系
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {}
可以看出,ScheduledThreadPoolExecutor继承了ThreadPoolExecutor类,实现了ScheduledExecutorService接口。其构造函数如下:
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
构造函数中调用了super方法,super方法其实是ThreadPoolExecutor类的构造函数,如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
从上述关系看出,ScheduledThreadPoolExecutor其实是ThreadPoolExecutor线程池衍生品,使用了DelayedWorkQueue线程池队列,线程池容量无边界,添加了延迟后运行命令,或者定期执行命令等属性。
一个例子
import java.util.concurrent.*;public class ScheduleTest { public static void main(String[] args) throws InterruptedException,ExecutionException{ ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(10); executScheduleWithFixedDelay(executorService); executScheduleAtFixedRate(executorService); executSchedule(executorService); System.out.println("over"); executorService.shutdown(); } // 间隔3秒执行一次 public static void executScheduleWithFixedDelay(ScheduledExecutorService executorService) throws InterruptedException,ExecutionException{ ScheduledFuture<?> result = executorService.scheduleWithFixedDelay( new Runnable() { @Override public void run() { System.out.println("scheduleWithFixedDelay-" + System.currentTimeMillis()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } },1000, 3000,TimeUnit.MILLISECONDS ); result.get(); } // 线程在第4秒开始执行 public static void executScheduleAtFixedRate(ScheduledExecutorService executorService) throws InterruptedException,ExecutionException{ ScheduledFuture<?> result = executorService.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("scheduleAtFixedRate-" + System.currentTimeMillis()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } },1000, 4000,TimeUnit.MILLISECONDS ); result.get(); } // 线程延迟4秒执行,仅执行一次 public static void executSchedule(ScheduledExecutorService executorService) throws InterruptedException,ExecutionException{ ScheduledFuture<?> result = executorService.schedule( new Runnable() { @Override public void run() { System.out.println("schedule-" + System.currentTimeMillis()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } },4000, TimeUnit.MILLISECONDS ); result.get(); }}
例子中也可以调用Executors的静态方法获取ScheduledExecutorService实例:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
这个例子引出了ScheduledThreadPoolExecutor调度线程池启动的3方法:
- scheduleWithFixedDelay:线程延迟执行。
- scheduleAtFixedRate:线程依照时间表执行,如果到指定时间点线程还没有执行完毕,则放弃该时间点,执行完毕后继续执行下一个线程。
- schedule:创建并执行在给定延迟后启用的一次性操作。
相关方法执行结果参考:
源码说明
scheduleWithFixedDelay方法:
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); if (delay <= 0) throw new IllegalArgumentException(); ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(-delay)); RunnableScheduledFuture<Void> t = decorateTask(command, sft); sft.outerTask = t; delayedExecute(t); return t;}
任务添加到队列后,工作线程会从队列获取并移除到期的元素,然后执行run方法,所以下面看看ScheduledFutureTask的run方法如何实现定时调度的。
其中ScheduledFutureTask封装定时任务内部类,重点关注其run方法。
ScheduledFutureTask(Runnable r, V result, long ns, long period) { super(r, result); this.time = ns; this.period = period; this.sequenceNumber = sequencer.getAndIncrement(); }public void run() { boolean periodic = isPeriodic(); if (!canRunInCurrentRunState(periodic)) cancel(false); //仅执行一次 else if (!periodic) ScheduledFutureTask.super.run(); //定时任务 else if (ScheduledFutureTask.super.runAndReset()) { setNextRunTime(); //重新加入该任务到delay队列 reExecutePeriodic(outerTask); } }
定时调度是先从队列获取任务然后执行,然后在重新设置任务时间,在把任务放入队列实现的。
如果任务执行时间大于delay时间则等任务执行完毕后的delay时间后在次调用任务,不会同一个任务并发执行。
scheduleAtFixedRate、schedule方法原理如出一辙。
参考
1、http://ifeve.com/33981-2/
2、类 ScheduledThreadPoolExecutor
- Java中调度线程池ScheduledThreadPoolExecutor原理探究
- Java中调度线程池ScheduledThreadPoolExecutor原理探究
- Java调度线程池ScheduledThreadPoolExecutor源码分析
- Java线程池架构2-多线程调度器(ScheduledThreadPoolExecutor)
- Java中线程池ThreadPoolExecutor原理探究
- Java线程调度器ScheduledThreadPoolExecutor 分析
- 线程池原理(四):ScheduledThreadPoolExecutor
- Java线程调度ScheduledThreadPoolExecutor简单使用样例
- 三、ScheduledThreadPoolExecutor 支持周期调度执行线程池解析
- Android Java 线程池 ScheduledThreadPoolExecutor源码篇
- java线程池系列(3)-ScheduledThreadPoolExecutor
- java 多线程调度器(ScheduledThreadPoolExecutor)
- Java多线程调度器(ScheduledThreadPoolExecutor)
- Java线程池类ThreadPoolExecutor、ScheduledThreadPoolExecutor及Executors工厂类
- Java线程池自学手册ScheduledThreadPoolExecutor的使用
- Java线程池类ThreadPoolExecutor、ScheduledThreadPoolExecutor及Executors工厂类
- Java线程池类ThreadPoolExecutor、ScheduledThreadPoolExecutor及Executors工厂类
- 线程池源码解析与原理探究
- 对象的归档/解挡
- js和jquery获取元素的方法
- freeRTOS计算任务堆栈使用情况:
- HDU-2064:汉诺塔III
- 【概率证明】—— sum and product rules of probability
- Java中调度线程池ScheduledThreadPoolExecutor原理探究
- Python入门系列——第3篇
- 常用数据结构
- Scikit-Learn各算法详细参数速查手册(中文)
- 如何完成卷积神经网络有关的毕业设计
- 虚拟化技术
- msm8x16 耳机阻抗检测
- 【每日一题-7】min栈实现与第一次只出现两次的字符
- 【Java学习之路】如何去除数组里面的0