Timer和ScheduledThreadPoolExecuto

2017-08-16  本文已影响0人  cxjhihihi

前言

在一些简单的时间调度任务时,常用的是Timer和ScheduledThreadPoolExecutor 两种解决方案。在jdk1.5之后,推荐使用ScheduledThreadPoolExecutor。为什么?

缺陷

Timer的缺陷:

1、Timer是单线程。
假如task1是延时1s后执行,task2延时3s后执行,假如task1的执行时间超过了2s,那么task2的延时会超过3s

        final long start = System.currentTimeMillis();
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {

                System.out.println("task1 useTime ! " + (System.currentTimeMillis() - start));
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task2 useTime ! " + (System.currentTimeMillis() - start));
            }
        };
        Timer timer = new Timer();
        timer.schedule(task1, 1000);
        timer.schedule(task2, 3000);

看下执行结果

task1 useTime ! 1006
task2 useTime ! 5009

结果可见,当task1的执行时间超过了4s,因此task3是在第1+4秒后执行

2、Timer当执行过程中某个任务出现RuntimeException时,会中断所有任务的执行。

task1抛出RuntimeException,task2周期性执行,也会因为task1的异常而中断。

 final TimerTask task1 = new TimerTask()  
            {  
      
                @Override  
                public void run()  
                {  
                    throw new RuntimeException();  
                }  
            };  
      
            final TimerTask task2 = new TimerTask()  
            {  
      
                @Override  
                public void run()  
                {  
                    System.out.println("task2 invoked!");  
                }  
            };  
              
            Timer timer = new Timer();  
            timer.schedule(task1, 100);  
            timer.scheduleAtFixedRate(task2, new Date(), 1000);  

res:

task2 invoked!
Exception in thread "Timer-0" java.lang.RuntimeException
at com.demo.cxjhihihi.TimerTest$1.run(TimerTest.java:18)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

而当使用线程池时,则不会有这个问题的存在。

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        final TimerTask task1 = new TimerTask() {

            @Override
            public void run() {
                System.out.println("runtime error");
                throw new RuntimeException();
            }
        };

        final TimerTask task2 = new TimerTask() {

            @Override
            public void run() {
                System.out.println("task2 invoked!");
            }
        };
        executorService.schedule(task1, 1, TimeUnit.SECONDS);
        executorService.scheduleAtFixedRate(task2, 1, 3, TimeUnit.SECONDS);

res:

runtime error
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!

可见当task1出现异常时,并不影响其余任务的继续执行

3、Timer执行周期任务时依赖系统时间
不知道怎么解释,要不你们使用Timer执行任务时,修改一下系统时间试试。。。很酸爽。ScheduledExecutorService基于时间的延迟,不会由于系统时间的改变发生执行变化。

上一篇 下一篇

猜你喜欢

热点阅读