原创文章,如需转载,请注明出处。
关于Timer的几个问题。 Java5.0以后版本,推荐使用ScheduledThreadPoolExecutor替代Timer。
1.Timer对任务的调度依赖于系统时间。
如下示例,如果把系统时间改为“2010-10-01 00:00:00”,那么运行代码,任务会立即执行。
示例代码: |
import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask;
public class OutOfTime { public static void main(String[] args) throws Exception { Timer timer = new Timer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date date= sdf.parse("2010-10-01 00:00:00"); System.out.println(date); timer.schedule(new Task("task"), date);
}
static class Task extends TimerTask { private String name; public Task(String name){ this.name=name; } public void run() { System.out.println(name); } } } |
2.Timer单线程执行任务,任务有可能丢失或执行时间不准确。
Timer执行任务时只是创建了单个线程。如果一个时间任务执行的时间比较长,那么其他任务执行时间的准确性就会受影响。比如每隔1秒执行一次短任务,中间有个长任务在当前时间延迟1秒后执行,执行时间超过5秒,那么短任务就有可能丢失或者在5秒后连续快速的执行而非每隔1秒。
示例代码: |
import java.util.Date; import java.util.Timer; import java.util.TimerTask; import static java.util.concurrent.TimeUnit.SECONDS;
public class OutOfTime { public static void main(String[] args) throws Exception { Timer timer = new Timer(); Date date = new Date(); timer.scheduleAtFixedRate(new ShortTask("ShortTask"+1), date,1000); timer.schedule(new LongTask("LongTask"+2), 1000); }
static class ShortTask extends TimerTask { private String name; public ShortTask(String name){ this.name=name; } public void run() { System.out.println(name); } }
static class LongTask extends TimerTask { private String name; public LongTask(String name){ this.name=name; } public void run() { try { SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name); } } } |
3.Timer的线程泄漏问题。
如果TimerTask抛出未检查的异常,Timer将产生无法预料的行为。Timer线程并不捕获异常,所以,TimerTask抛出未检查的异常会终止Timer线程。在这种情况下,Timer也不会恢复线程,而是错误地认为整个Timer线程被取消了。这时,已经在计划中但是还没有执行的TimerTask就再也不会运行了,新的任务也不会被安排了。
示例代码: |
import java.util.Timer; import java.util.TimerTask; import static java.util.concurrent.TimeUnit.SECONDS;
public class OutOfTime { public static void main(String[] args) throws Exception { Timer timer = new Timer(); timer.schedule(new ThrowTask(), 1); SECONDS.sleep(1); timer.schedule(new ThrowTask(), 1); SECONDS.sleep(5); }
static class ThrowTask extends TimerTask { public void run() { throw new RuntimeException(); } } } |
抛出的异常: |
Exception in thread "Timer-0" java.lang.RuntimeException at com.timer.test.OutOfTime$ThrowTask.run(OutOfTime.java:18) at java.util.TimerThread.mainLoop(Unknown Source) at java.util.TimerThread.run(Unknown Source) Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled. at java.util.Timer.sched(Unknown Source) at java.util.Timer.schedule(Unknown Source) at com.timer.test.OutOfTime.main(OutOfTime.java:12) |