Timer与ScheduledExecutorService间的抉择

多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。

阿里巴巴规约扫描提示 Timer执行多个task,当一个task抛出异常所存在缺陷的问题。

由于Timer是单线程的,当执行多个任务时,一个任务抛出异常,接下来的任务就不会再继续执行。

例子一、使用timer执行两个任务,第二个任务为周期性任务(每隔一段时间执行一次)

/**
     * timer执行两个任务
     */
    @Test
    public void TimerDemo1() {
        final TimerTask task1 = new TimerTask(){
            @Override
            public void run()
            {
                System.out.println("99999");
//                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);
    }

执行结果:

11111111111111111111
task2 invoked!
99999
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!

说明:任务task1执行一次,然后周期性执行task2

接下来让task1抛出异常

执行结果为:

11111111111111111111
task2 invoked!
99999
Exception in thread "Timer-0" java.lang.RuntimeException
    at cn.dhcc.thread.TimerTest$1.run(TimerTest.java:34)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

说明:由于task1抛出异常,task2也不能继续执行了

例子二、使用ScheduledExecutorService执行两个任务

/**
     * schedule执行两个任务
     */
    @Test
    public void ScheduledDemo1() {
        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!");
            }
        };    
                
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.schedule(task1, 100, TimeUnit.MILLISECONDS);
        pool.scheduleAtFixedRate(task2, 0 , 1000, TimeUnit.MILLISECONDS);
    }

执行结果:

11111111111111111111
task2 invoked!
抛出异常
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!
task2 invoked!

说明:在task1抛出异常后,task2仍然执行

在单任务执行时,两者差不多,Timer的性能会更好一点。

 

你可能感兴趣的:(多线程)