Timer与ScheduledExecutorService间的抉择

java.util.Timer计时器有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务")。
但是,Timer存在一些缺陷,因此你应该考虑使用ScheduledThreadPoolExecutor作为代替品,Timer对调度的支持是基于绝对时间,而不是相对时间的,
由此任务对系统时钟的改变是敏感的;ScheduledThreadExecutor只支持相对时间。

Timer的另一个问题在于,如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。
Timer线程并不捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程。
这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。
此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。
 
个人总结:timer的bug:60秒执行一次的话,如果用户修改了时间的话 那么时针都会归0,本来是临近10秒执行的时候timer又会重新计时一次 再等60才执行。

测试Timer的例子

 1 package com.bill99.test;
 2
 3 import java.util.Timer;
 4 import java.util.TimerTask;
 5
 6 public class TimerTest {
 7     private Timer timer = new Timer();
 8     //启动计时器
 9     public void lanuchTimer(){
10         timer.schedule(new TimerTask(){
11             public void run() {
12                 throw new RuntimeException();
13             }
14         }, 1000*3, 500);
15     }
16     //向计时器添加一个任务
17     public void addOneTask(){
18         timer.schedule(new TimerTask(){
19             public void run(){
20                 System.out.println("hello world");
21             }
22         }, 1000*1,1000*5);
23     }
24
25     public static void main(String[] args) throws Exception {
26         TimerTest test = new TimerTest();
27         test.lanuchTimer();
28         Thread.sleep(1000*5);//5秒钟之后添加一个新任务
29         test.addOneTask();
30     }
31 }  

运行该程序,Timer会抛出一个RumtimeException和java.lang.IllegalStateException:Timer already cancelled.
常言道,真是祸不单行,Timer还将它的问题传染给下一个倒霉的调用者,这个调用者原本试图提交一个TimerTask的,你可能希望程序会一直运行下去,然而实际情况如程序所示5秒钟后就中止了,还伴随着一个异常,异常的消息是"Timer already cancelled"。ScheduledThreadPoolExector妥善地处理了这个异常的任务,所以说在java5.0或更高的JDK中,几乎没有理由再使用Timer了。

用ScheduledThreadPoolExector改进后的例子

 1 package com.bill99.test;
 2
 3 import java.util.concurrent.Executors;
 4 import java.util.concurrent.ScheduledExecutorService;
 5 import java.util.concurrent.TimeUnit;
 6
 7 public class ScheduledExecutorTest {
 8     //线程池能按时间计划来执行任务,允许用户设定计划执行任务的时间,int类型的参数是设定
 9     //线程池中线程的最小数目。当任务较多时,线程池可能会自动创建更多的工作线程来执行任务
10     //此处用Executors.newSingleThreadScheduledExecutor()更佳。
11     public ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1);
12     //启动计时器
13     public void lanuchTimer(){
14         Runnable task = new Runnable() {
15             public void run() {
16                 throw new RuntimeException();
17             }
18         };
19         scheduExec.scheduleWithFixedDelay(task, 1000*5, 1000*10, TimeUnit.MILLISECONDS);
20     }
21     //添加新任务
22     public void addOneTask(){
23         Runnable task = new Runnable() {
24             public void run() {
25                 System.out.println("welcome to china");
26             }
27         };
28         scheduExec.scheduleWithFixedDelay(task, 1000*1, 1000, TimeUnit.MILLISECONDS);
29     }
30
31     public static void main(String[] args) throws Exception {
32         ScheduledExecutorTest test = new ScheduledExecutorTest();
33         test.lanuchTimer();
34         Thread.sleep(1000*5);//5秒钟之后添加新任务
35         test.addOneTask();
36     }
37 }  

时间: 2024-08-08 13:58:10

Timer与ScheduledExecutorService间的抉择的相关文章

手把手实现一条延时消息

前言 近期在维护公司的调度平台,其中有个关键功能那就是定时任务:定时任务大家平时肯定接触的不少,比如 JDK 中的 Timer.ScheduledExecutorService.调度框架 Quartz 等. 通常用于实现 XX 时间后的延时任务,或周期性任务: 比如一个常见的业务场景:用户下单 N 分钟未能支付便自动取消订单. 实现这类需求通常有两种方式: 轮询定时任务:给定周期内扫描所有未支付的订单,查看时间是否到期. 延时消息:订单创建的时候发送一条 N 分钟到期的信息,一旦消息消费后便可判

高仿优酷Android客户端图片左右滑动(自动切换)

本例是用ViewPager去做的实现,支持自动滑动和手动滑动,不仅优酷网,实际上有很多商城和门户网站都有类似的实现: 具体思路: 1. 工程中需要添加android-support-v4.jar,才能使用ViewPager控件. 2. 图片的自动切换: 可使用Timer或者ScheduledExecutorService,这个有多重方式可以实现. 同时要切换底部的dots(园点) 3.Handler+Message机制更新UI,这个相信大家都很熟练,不再描述 4. 实现的一些细节:注意本例中的优

唯有“精细运营”才能拯救中国手机?

智能手机市场意兴阑珊,但这个市场中的数据依旧是最耀眼的数据,尤其是出货量.利润率等硬指标,更是牵动着整个业界的神经.前不久,国外权威调查机构Strategy Analytic最新数据显示,2016年全球智能手机总利润估算为537亿美元,苹果拿走了449亿美元,占比达到了79.2%,三星的利润是83亿美元,占比14.6%,这意味着其他品牌手机的利润率依旧低得可怜,坦白讲,这种状况在早先几年基本正常,毕竟,中国品牌的手机还没有卖出去多少,但今时不同往日,国产手机在出货量上已然实现快速增长,华为.OP

ViewPager轮播图

ViewPager: 轮播图 下面的ViewPager由LinearLayout,textView,点的容器组成; ViewPager 页面切换,定时页面切换 VP技术点: 1.使用第三方UI类,只需要将完整包名加入就行2.Timer和ScheduledExecutorService3.Handler+Message或者runOnUiThread(runnable)更新界面ui4.ViewPager的适配器类 VP步骤: 1.布局 ##viewpager的使用方法       注意: 1.首先在

代开发票“猖獗” 带您揭开背后巨大黑色利益链

代开发票"猖獗" 带您揭开背后巨大黑色利益链 2013年07月19日08:09河南法制报[微博]郭跃华我要评论(0) 通过代开发票公司开发票,只需支付所开发票金额1%至2%的费用(比正常税率低好几倍),而且开具的发票能够通过税务部门的审核.当前,代开发票已经形成了庞大的黑色利益链条,导致了严重的偷税.逃税和漏税,在各方得益的背后是国家利益的损失. 代开发票者手中的"发票"从何而来?为何能够躲避税务部门的审查而能够正常走账?记者对此进行了调查. □记者郭跃华 现象:

【Java线程】Java线程池ExecutorService

示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; public class Ch09_Executor { private static void run(ExecutorService threadPool) { for(int i = 1; i < 5; i++)

Unity_UGUI翻译(2) Basic Layout(基本布局)

Basic Layout(基本布局) In this section we’ll look at how you can position UI elements relative to the Canvas and each other. If you want to test yourself while reading, you can create an Image using the menu GameObject > UI > Image. 在这一节中,我们将会尝试如何摆放UI元素

Chromium on Android: Android系统上Chromium主消息循环的实现分析

摘要:刚一开始接触Chromium on Android时,就很好奇Chromium的主消息循环是怎么整合到Android应用程序中的.对于Android程序来说,一旦启动,主线程就会有一个Java层的消息循环处理用户输入事件等系统事件,而对Chromium来说,它有自己另一套消息循环的实现,这个实现有哪些特点,又将如何无缝整合到Android Java层的消息循环中去,正是本文所要讨论的话题. 原创文章系列,转载请注明原始出处为http://blog.csdn.net/hongbomin/ar

Chromium on Android: Android在系统Chromium为了实现主消息循环分析

总结:刚开始接触一个Chromium on Android时间.很好奇Chromium主消息循环是如何整合Android应用. 为Android计划,一旦启动,主线程将具有Java消息层循环处理系统事件,如用户输入事件,而Chromium为,己还有一套消息循环的实现,这个实现有哪些特点.又将怎样无缝整合到Android Java层的消息循环中去,正是本文所要讨论的话题. 原创文章系列.转载请注明原始出处为http://blog.csdn.net/hongbomin/article/details