Timer的缺陷

三、Timer的缺陷

  3.1、Timer的缺陷

  Timer计时器可以定时(指定时间执行任务)、延迟(延迟5秒执行任务)、周期性地执行任务(每隔个1秒执行任务),但是,Timer存在一些缺陷。首先Timer对调度的支持是基于绝对时间的,而不是相对时间,所以它对系统时间的改变非常敏感。其次Timer线程是不会捕获异常的,如果TimerTask抛出的了未检查异常则会导致Timer线程终止,同时Timer也不会重新恢复线程的执行,他会错误的认为整个Timer线程都会取消。同时,已经被安排单尚未执行的TimerTask也不会再执行了,新的任务也不能被调度。故如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。

  1、Timer管理时间延迟缺陷

  前面Timer在执行定时任务时只会创建一个线程任务,如果存在多个线程,若其中某个线程因为某种原因而导致线程任务执行时间过长,超过了两个任务的间隔时间,会发生一些缺陷:

  public class TimerTest04 {

  private Timer timer;

  public long start;

  public TimerTest04(){

  this.timer = new Timer();

  start = System.currentTimeMillis();

  }

  public void timerOne(){

  timer.schedule(new TimerTask() {

  public void run() {

  System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start));

  try {

  Thread.sleep(4000);    //线程休眠3000

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  }, 1000);

  }

  public void timerTwo(){

  timer.schedule(new TimerTask() {

  public void run() {

  System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start));

  }

  }, 3000);

  }

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

  TimerTest04 test = new TimerTest04();

  test.timerOne();

  test.timerTwo();

  }

  }

  按照我们正常思路,timerTwo应该是在3s后执行,其结果应该是:

  timerOne invoked ,the time:1001

  timerOne invoked ,the time:3001

  但是事与愿违,timerOne由于sleep(4000),休眠了4S,同时Timer内部是一个线程,导致timeOne所需的时间超过了间隔时间,结果:

  timerOne invoked ,the time:1000

  timerOne invoked ,the time:5000

  2、Timer抛出异常缺陷

  如果TimerTask抛出RuntimeException,Timer会终止所有任务的运行。如下:

  public class TimerTest04 {

  private Timer timer;

  public TimerTest04(){

  this.timer = new Timer();

  }

  public void timerOne(){

  timer.schedule(new TimerTask() {

  public void run() {

  throw new RuntimeException();

  }

  }, 1000);

  }

  public void timerTwo(){

  timer.schedule(new TimerTask() {

  public void run() {

  System.out.println("我会不会执行呢??");

  }

  }, 1000);

  }

  public static void main(String[] args) {

  TimerTest04 test = new TimerTest04();

  test.timerOne();

  test.timerTwo();

  }

  }

  运行结果:timerOne抛出异常,导致timerTwo任务终止。

  Exception in thread "Timer-0" java.lang.RuntimeException

  at com.chenssy.timer.TimerTest04$1.run(TimerTest04.java:25)

  at java.util.TimerThread.mainLoop(Timer.java:555)

  at java.util.TimerThread.run(Timer.java:505)

  对于Timer的缺陷,我们可以考虑 ScheduledThreadPoolExecutor 来替代。Timer是基于绝对时间的,对系统时间比较敏感,而ScheduledThreadPoolExecutor 则是基于相对时间;Timer是内部是单一线程,而ScheduledThreadPoolExecutor内部是个线程池,所以可以支持多个任务并发执行。

  3.2、用ScheduledExecutorService替代Timer

  1、解决问题一:

  public class ScheduledExecutorTest {

  private  ScheduledExecutorService scheduExec;

  public long start;

  ScheduledExecutorTest(){

  this.scheduExec =  Executors.newScheduledThreadPool(2);

  this.start = System.currentTimeMillis();

  }

  public void timerOne(){

  scheduExec.schedule(new Runnable() {

  public void run() {

  System.out.println("timerOne,the time:" + (System.currentTimeMillis() - start));

  try {

  Thread.sleep(4000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  },1000,TimeUnit.MILLISECONDS);

  }

  public void timerTwo(){

  scheduExec.schedule(new Runnable() {

  public void run() {

  System.out.println("timerTwo,the time:" + (System.currentTimeMillis() - start));

  }

  },2000,TimeUnit.MILLISECONDS);

  }

  public static void main(String[] args) {

  ScheduledExecutorTest test = new ScheduledExecutorTest();

  test.timerOne();

  test.timerTwo();

  }

  }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值