Timer与TimerTask之二:timer使用缺陷及用ScheduledThreadPoolExecutor解决

1.缺陷一:Timer由于内部只要一个线程,管理多个任务的时候,一个任务延时,后面的任务就会跟着延时。用下面的例子说明:

package com.dxz.timer;

import java.util.Timer;
import java.util.TimerTask;

public class TimerTaskTest {
    private static long startTime;

    public static void main(String[] args) {

        // 创建一个定时task1
        TimerTask task1 = new TimerTask() {

            @Override
            public void run() {
                System.out.println("task1 excude ..." + (System.currentTimeMillis() - startTime));
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        // 创建一个定时task2
        TimerTask task2 = new TimerTask() {

            @Override
            public void run() {
                System.out.println("task2 excude ..." + (System.currentTimeMillis() - startTime));
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Timer timer = new Timer("TimerThread");
        startTime = System.currentTimeMillis();
        // 第1个任务1s后,执行
        timer.schedule(task1, 1000);
        // 第2个任务3s后,执行
        timer.schedule(task2, 3000);

    }

}

结果:

task1 excude ...1001
task2 excude ...4002

从上面的代码看出,第一个任务1s后执行,第二个任务3s后执行。实际上task2是在4s后才执行的,因为Timer内部是一个线程,而task1所需的时间超过了两个任务的间隔时间导致。下面使用ScheduledThreadPool解决上面的问题:

package com.dxz.timer;

import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolTest1 {

    private static long startTime;

    public static void main(String[] args) {
        ScheduledExecutorService newExecutorService = Executors.newScheduledThreadPool(2);

        // 创建一个定时task1
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " excude ..."
                        + (System.currentTimeMillis() - startTime) + "ms");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        // 创建一个定时task2
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " excude ..."
                        + (System.currentTimeMillis() - startTime) + "ms");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        startTime = System.currentTimeMillis();
        // 第1个任务1000 表示1s后,执行
        newExecutorService.schedule(task1, 1000, TimeUnit.MILLISECONDS);
        // 第2个任务3000 表示3s后,执行
        newExecutorService.schedule(task2, 3000, TimeUnit.MILLISECONDS);

    }

}

结果:

pool-1-thread-1 excude ...1001ms
pool-1-thread-2 excude ...3002ms

2、缺陷二:

package com.dxz.timer;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimerTaskTest2 {
    private static long startTime;

    public static void main(String[] args) {
        // 创建一个定时task1
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                throw new RuntimeException("运行时异常");
            }
        };
        // 创建一个定时task2
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task2 excude ..." + (System.currentTimeMillis() - startTime));
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Timer timer = new Timer("TimerThread");
        startTime = System.currentTimeMillis();
        timer.schedule(task1, 100);
        timer.scheduleAtFixedRate(task2, new Date(), 1000);

    }

}

结果:

task2 excude ...2
Exception in thread "TimerThread" java.lang.RuntimeException: 运行时异常
    at com.dxz.timer.TimerTaskTest2$1.run(TimerTaskTest2.java:15)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

使用ScheduledExecutorService来解决:

package com.dxz.timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolTest2 {

    private static long startTime;

    public static void main(String[] args) {
        ScheduledExecutorService newExecutorService = Executors.newScheduledThreadPool(1);

        // 创建一个定时task1
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                new RuntimeException();
            }
        };
        // 创建一个定时task2
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " excude ..." + (System.currentTimeMillis() - startTime) + "ms");
            }
        };

        startTime = System.currentTimeMillis();
        newExecutorService.schedule(task1, 0, TimeUnit.MILLISECONDS);
        // 第2个任务3000 表示3s后,执行
        newExecutorService.scheduleAtFixedRate(task2,1000, 1000, TimeUnit.MILLISECONDS);

    }

}

结果:

pool-1-thread-1 excude ...1002ms
pool-1-thread-1 excude ...2001ms
pool-1-thread-1 excude ...3002ms
pool-1-thread-1 excude ...4002ms

 

posted on 2012-11-14 11:34  duanxz  阅读(453)  评论(0编辑  收藏  举报