ScheduledExecutorService和timer的异同

Stella981
• 阅读 685

先来个传统的Timer的例子:

[java] view plain copy

  1. package com.jerry.concurrency;  

  2. import java.text.ParseException;  

  3. import java.text.SimpleDateFormat;  

  4. import java.util.Date;  

  5. import java.util.Timer;  

  6. import java.util.TimerTask;  

  7. public class TraditionalTask {  

  8.     public static void main(String[] args) throws ParseException {  

  9.         Timer myTimer = new Timer();  

  10.         myTimer.schedule(new Worker(), 1000);//1秒后执行  

  11. //      2012-02-28 09:58:00执行  

  12.         myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"));  

  13.         myTimer.schedule(new Worker(), 5000,1000);//5秒后执行 每一秒执行一次  

  14. //      2012-02-28 09:58:00执行一次 以后每秒执行一次,如果设定的时间点在当前时间之前,任务会被马上执行,然后开始按照设定的周期定时执行任务  

  15.         myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);  

  16.         myTimer.scheduleAtFixedRate(new Worker(), 5000,1000);//5秒后执行 每一秒执行一次 如果该任务因为某些原因(例如垃圾收集)而延迟执行,那么接下来的任务会尽可能的快速执行,以赶上特定的时间点  

  17.         myTimer.scheduleAtFixedRate(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);//和上个类似  

  18.     }  

  19. }  

  20. class Worker extends TimerTask {  

  21.     @Override  

  22.     public void run() {  

  23.         System.out.println("我被执行了!"+"时间是:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));  

  24.     }  

  25. }

  

传统的timer的缺点:Timer对任务的调度是基于绝对时间的;所有的TimerTask只有一个线程TimerThread来执行,因此同一时刻只有一个TimerTask在执行;任何一个TimerTask的执行异常都会导致Timer终止所有任务;由于基于绝对时间并且是单线程执行,因此在多个任务调度时,长时间执行的任务被执行后有可能导致短时间任务快速在短时间内被执行多次或者干脆丢弃多个任务。

ScheduledExecutorService克服了上述缺点,例子如下:

[java] view plain copy

  1. <span style="font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;font-size:13px;">package com.jerry.concurrency;  

  2. import java.util.concurrent.Executors;  

  3. import java.util.concurrent.ScheduledExecutorService;  

  4. import java.util.concurrent.TimeUnit;  

  5. public class TestScheduledExecutorService{  

  6.     public static void main(String[] args) throws Exception{  

  7.         ScheduledExecutorService execService =   Executors.newScheduledThreadPool(3);  

  8.         // 5秒后开始执行 每个2秒执行一次,如果有的任务执行要花费比其周期更长的时间,则将推迟后续执行,但不会同时执行  

  9. //        每次相隔相同的时间执行任务,如果任务的执行时间比周期还长,那么下一个任务将立即执行  

  10.         execService.scheduleAtFixedRate(new Runnable() {  

  11.             public void run() {  

  12.                 System.out.println("任务:"+Thread.currentThread().getName()+" 执行了,时间为: "+System.currentTimeMillis());  

  13.                 try {  

  14.                     Thread.sleep(1000L);  

  15.                 } catch (Exception e) {  

  16.                     e.printStackTrace();  

  17.                 }  

  18.             }  

  19.         }, 5, 2, TimeUnit.SECONDS);  

  20.         //5秒后开始执行 每个2秒执行一次,保证固定的延迟为2秒 下一个任务的开始时间与上一个任务的结束时间间隔相同  

  21.         execService.scheduleWithFixedDelay(new Runnable() {  

  22.             public void run() {  

  23.                 System.out.println("任务:"+Thread.currentThread().getName()+"执行了,时间为:"+System.currentTimeMillis());  

  24.                 try {  

  25.                     Thread.sleep(1000L);  

  26.                 } catch (Exception e) {  

  27.                     e.printStackTrace();  

  28.                 }  

  29.             }  

  30.         }, 5, 2, TimeUnit.SECONDS);  

  31.         Thread.sleep(10000L);  

  32.         execService.shutdown();  

  33.     }  

  34. }  

 

本文同步分享在 博客“xiangzhihong8”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java 反射机制
1.考虑安全访问范围内的属性,没有权限访问到的属性不读取\java\ viewplain(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fjiao_zg%2Farticle%2Fdetails%2F77897748%23)copy
Wesley13 Wesley13
3年前
java获取jdk、系统、服务器等信息
1、获取jdk信息\java\ viewplain(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fzgmzyr%2Farticle%2Fdetails%2F6903509%23)copy(https://www.oschina.
Wesley13 Wesley13
3年前
java创建文件和目录
\java\ viewplain(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fqiaqia609%2Farticle%2Fdetails%2F11048463%23)copy(https://www.oschina.net/action
Wesley13 Wesley13
3年前
MarkDown 页内跳转实现
目录:1\.先定义一个锚(id)(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fjingbin_%2Farticle%2Fdetails%2F53075290%23one)2\.然后使用markdown的语法:(htt
Stella981 Stella981
3年前
Android BLE 总结-源码篇(BluetoothLeAdvertiser)
在做AndroidBLE的应用程序时,我们发出广播数据是调用BluetoothLeAdvertiser的startAdvertising方法,如下所示:\java\viewplain(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fan
Stella981 Stella981
3年前
Python简单密码加密程序,加盐(salt)md5
\python\ viewplain(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fcolourless%2Farticle%2Fdetails%2F41440963%23)copy(https://www.oschina.net/a
Stella981 Stella981
3年前
QML之TabWidget
转自:http://blog.csdn.net/liuhongwei123888/article/details/6174839\javascript\ viewplain(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fliuho
Wesley13 Wesley13
3年前
MongoDB 分片1
第一步:准备数据节点必须添加–shardsvr参数。\html\ viewplain(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fmlz_2%2Farticle%2Fdetails%2F71703153%23)copy
Wesley13 Wesley13
3年前
Intellij idea 快捷键(1)
使用Intellijidea时,想要快捷生成for循环代码块itar生成arrayfor代码块\java\ viewplain(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fcsdnimg.cn%2Frelease%2Fphoenix%2F%23) cop