JDK 1.5开始提供ScheduledThreadPoolExecutor类,ScheduledThreadPoolExecutor类继承ThreadPoolExecutor类重用线程池实现了任务的周期性调度功能 。在JDK 1.5之前,实现任务的周期性调度主要使用的是Timer类和TimerTask类 。本文,就简单介绍下ScheduledThreadPoolExecutor类与Timer类的区别,ScheduledThreadPoolExecutor类相比于Timer类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例 。
二者的区别线程角度
- Timer是单线程模式,如果某个TimerTask任务的执行时间比较久,会影响到其他任务的调度执行 。
- ScheduledThreadPoolExecutor是多线程模式,并且重用线程池,某个ScheduledFutureTask任务执行的时间比较久,不会影响到其他任务的调度执行 。
- Timer调度是基于操作系统的绝对时间的,对操作系统的时间敏感,一旦操作系统的时间改变,则Timer的调度不再精确 。
- ScheduledThreadPoolExecutor调度是基于相对时间的,不受操作系统时间改变的影响 。
- Timer不会捕获TimerTask抛出的异常,加上Timer又是单线程的 。一旦某个调度任务出现异常,则整个线程就会终止,其他需要调度的任务也不再执行 。
- ScheduledThreadPoolExecutor基于线程池来实现调度功能,某个任务抛出异常后,其他任务仍能正常执行 。
- Timer中执行的TimerTask任务整体上没有优先级的概念,只是按照系统的绝对时间来执行任务 。
- ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,这也就说明了ScheduledFutureTask类中实现了两个非常重要的方法,一个是java.lang.Comparable接口的compareTo方法,一个是java.util.concurrent.Delayed接口的getDelay方法 。在ScheduledFutureTask类中compareTo方法方法实现了任务的比较,距离下次执行的时间间隔短的任务会排在前面,也就是说,距离下次执行的时间间隔短的任务的优先级比较高 。而getDelay方法则能够返回距离下次任务执行的时间间隔 。
- Timer不支持对任务的排序 。
- ScheduledThreadPoolExecutor类中定义了一个静态内部类DelayedWorkQueue,DelayedWorkQueue类本质上是一个有序队列,为需要调度的每个任务按照距离下次执行时间间隔的大小来排序
- Timer中执行的TimerTask类只是实现了java.lang.Runnable接口,无法从TimerTask中获取返回的结果 。
- ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类继承了FutureTask类,能够通过Future来获取返回的结果 。
二者简单的示例这里,给出使用Timer和ScheduledThreadPoolExecutor实现定时调度的简单示例,为了简便,我这里就直接使用匿名内部类的形式来提交任务 。
Timer类简单示例源代码示例如下所示 。
package io.binghe.concurrent.lab09;import java.util.Timer;import java.util.TimerTask;/** * @author binghe * @version 1.0.0 * @description 测试Timer */public class TimerTest {public static void main(String[] args) throws InterruptedException {Timer timer = new Timer();timer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {System.out.println("测试Timer类");}}, 1000, 1000);Thread.sleep(10000);timer.cancel();}}
运行结果如下所示 。测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类
ScheduledThreadPoolExecutor类简单示例源代码示例如下所示 。package io.binghe.concurrent.lab09;import java.util.concurrent.*;/** * @author binghe * @version 1.0.0 * @description 测试ScheduledThreadPoolExecutor */public class ScheduledThreadPoolExecutorTest {public static void main(String[] args) throwsInterruptedException {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);scheduledExecutorService.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("测试测试ScheduledThreadPoolExecutor");}}, 1, 1, TimeUnit.SECONDS);//主线程休眠10秒Thread.sleep(10000);System.out.println("正在关闭线程池...");// 关闭线程池scheduledExecutorService.shutdown();boolean isClosed;// 等待线程池终止do {isClosed = scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);System.out.println("正在等待线程池中的任务执行完成");} while(!isClosed);System.out.println("所有线程执行结束,线程池关闭");}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 甜面酱的用途
- 清冷中暗含唯美的签名 高雅会着迷会心动的优秀签名
- 火灾白烟和黑烟区别
- 牙膏可以代替洗洁精洗碗吗
- 自由感十足的高级杂系签名 乐观积极必定风生水起
- 高质量男性个性签名 三观很正的有格局男生签名
- 古代对神仙的雅称
- 马桶被卫生纸堵一般多久能通
- 切好的土豆丝放冰箱第二天能用吗
- 蜜蜂可以吃吗