Timer
schedule: 任务开始的时间 + period(时间片段),强调“固定间隔”地执行任务
scheduleAtFixedRate: 参数设定开始的时间 + period(时间片段),强调“固定频率”地执行任务
Timer的缺陷:
Timer被设计成支持多个定时任务,通过源码发现它有一个任务队列用来存放这些定时任务,并且启动了一个线程来处理。
通过这种单线程的方式实现,在存在多个定时任务的时候便会存在以下问题:
1、若任务A执行时间过长,将导致任务B延迟了启动时间!
2、若任务线程在执行队列中某个任务时,该任务抛出异常,将导致线程因跳出循环体而终止,即Timer停止了工作!
Timer示例说明:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task1: do task");
}
}, 0, 1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task2: sleep");
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 2 * 1000, 3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task3: throw Exception");
throw new RuntimeException("test");
}
}, 10 * 1000, 5000);
}
}
执行结果:
21:58:31 Task1: do task
21:58:32 Task2: sleep
21:58:37 Task1: do task
21:58:37 Task2: sleep
21:58:42 Task1: do task
Exception in thread "Timer-0" 21:58:42 Task3: throw Exception
java.lang.RuntimeException: test
at com.learn.schedule.TimerTest$3.run(TimerTest.java:39)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
ScheduledExecutorService示例:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
public class ScheduleTest {
public static void main(String[] args) {
int corePoolSize = 3;
ScheduledExecutorService pool = Executors.newScheduledThreadPool(corePoolSize);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task1: do task");
}
}, 0, 1, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task2: sleep");
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 3, 3, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()) + " Task3: throw Exception");
throw new RuntimeException("test");
}
}, 10, 5, TimeUnit.SECONDS);
}
}
corePoolSize =3 执行结果:
22:07:20 Task1: do task
22:07:21 Task1: do task
22:07:22 Task1: do task
22:07:23 Task1: do task
22:07:23 Task2: sleep
22:07:24 Task1: do task
22:07:25 Task1: do task
22:07:26 Task1: do task
22:07:27 Task1: do task
22:07:28 Task1: do task
22:07:28 Task2: sleep
22:07:29 Task1: do task
22:07:30 Task1: do task
22:07:30 Task3: throw Exception
22:07:31 Task1: do task
corePoolSize =1执行结果:
22:01:18 Task1: do task
22:01:19 Task1: do task
22:01:20 Task1: do task
22:01:21 Task1: do task
22:01:21 Task2: sleep
22:01:26 Task1: do task
22:01:26 Task1: do task
22:01:26 Task1: do task
22:01:26 Task2: sleep
22:01:31 Task1: do task
22:01:31 Task1: do task
22:01:31 Task1: do task
22:01:31 Task2: sleep
22:01:36 Task1: do task
22:01:36 Task3: throw Exception
22:01:36 Task1: do task
22:01:36 Task1: do task
22:01:36 Task2: sleep
1、将线程数设置为3,通过控制台打印可以看到Task1一直都在正常运行(任务时间间隔为1秒),并不受Task2的影响。Task3抛出异常后,虽然本身停止了调度,但没有影响到其他任务的调度。
2、将线程数设置为1,变成单线程跑时,结果和Timer一样,Task2会导致Task1延迟执行,但Task3抛异常不会影响到其他任务的调度。
参考
https://blog.csdn.net/guozebo/article/details/51090612