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 ...1001task2 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 ...1001mspool-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 ...2Exception 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 ...1002mspool-1-thread-1 excude ...2001mspool-1-thread-1 excude ...3002mspool-1-thread-1 excude ...4002ms