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