我们在开发中经常有定时调度某一个任务的需求,在java中常用的是通过定时调度线程池ScheduledThreadPoolExecutor来实现,这个线程池有两种方法
- scheduleAtFixedRate
- scheduleWithFixedDelay
光知道概念还是比较虚的,下面通过具体的例子来运行一下。
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class ScheduledThreadPoolTest { public static void main(String[] args) { ScheduledExecutorService pool = new ScheduledThreadPoolExecutor(1); int pollSecond = 2; pool.scheduleAtFixedRate(new TestRunner(), pollSecond / 10, pollSecond, TimeUnit.SECONDS); }
static class TestRunner implements Runnable { @Override public void run() {
System.out.println(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss SSS")); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
|
运行结果
scheduleAtFixedRate
- 当实验变量 Thread.sleep(2000); 值小于period 值
1 2 3 4 5 6
| 2018-04-08 09:44:58 239 2018-04-08 09:45:00 367 2018-04-08 09:45:02 367 2018-04-08 09:45:04 369 2018-04-08 09:45:06 369 2018-04-08 09:45:08 369
|
- 当实验变量 Thread.sleep(3000); 值大于period 值
1 2 3 4 5
| 2018-04-08 09:48:41 882 2018-04-08 09:48:44 969 2018-04-08 09:48:47 969 2018-04-08 09:48:50 969 2018-04-08 09:48:53 969
|
scheduleWithFixedDelay
- 当实验变量 Thread.sleep(2000); 值小于period 值
1 2 3 4 5 6
| 2018-04-08 09:50:29 325 2018-04-08 09:50:33 420 2018-04-08 09:50:37 421 2018-04-08 09:50:41 422 2018-04-08 09:50:45 423 2018-04-08 09:50:49 424
|
- 当实验变量 Thread.sleep(3000); 值大于period 值
1 2 3 4 5 6
| 2018-04-08 09:51:20 858 2018-04-08 09:51:26 036 2018-04-08 09:51:31 036 2018-04-08 09:51:36 038 2018-04-08 09:51:41 038 2018-04-08 09:51:46 039
|
结论
- scheduleAtFixedRate
- 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕,如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。
- 执行周期是 initialDelay 、initialDelay+period 、initialDelay + 2 * period} 、 … 如果延迟任务的执行时间大于了 period,比如为 5s,则后面的执行会等待5s才回去执行
- scheduleWithFixedDelay 是以上一个任务结束时开始计时,period时间过去后,立即执行, 由上面的运行结果可以看出,第一个任务开始和第二个任务开始的间隔时间是 第一个任务的运行时间+period