首页 > 代码库 > Java并发程序设计(8)线程池之用于定时器
Java并发程序设计(8)线程池之用于定时器
1.1. 线程池用于定时器
线程池用于定时器调度时,只能指定某个时间段后执行任务,而不能指定具体的时间点。
1.2. 只运行一次的定时器
5秒钟后运行指定任务的定时器,定时器任务只会被执行1次。
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.schedule( new Runnable(){ @Override public void run() { System.out.println("scheduled:" + new Date() + " " + Thread.currentThread().getId()); } }, 1000 * 5, TimeUnit.MILLISECONDS );
1.3. 固定比率的定时器
固定比率的定时器会在指定时间段之后首次运行任务,并在之后每隔固定时间段后重复运行任务。以下代码创建一个5秒后首次运行并每隔1秒重复1次的定时器。
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.scheduleAtFixedRate( new Runnable(){ @Override public void run() { System.out.println("scheduled:" + new Date() + " " + Thread.currentThread().getId()); } }, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );
scheduled:Sun Mar 12 19:55:07 CST 2017 8
scheduled:Sun Mar 12 19:55:08 CST 2017 8
scheduled:Sun Mar 12 19:55:09 CST 2017 10
scheduled:Sun Mar 12 19:55:10 CST 2017 10
scheduled:Sun Mar 12 19:55:11 CST 2017 10
scheduled:Sun Mar 12 19:55:12 CST 2017 10
scheduled:Sun Mar 12 19:55:13 CST 2017 11
scheduleAtFixedRate()这个函数的api doc是这样描述的:
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on. If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
Parameters:
command the task to execute
initialDelay the time to delay first execution
period the period between successive executions
unit the time unit of the initialDelay and period parameters
Returns:
a ScheduledFuture representing pending completion of the task, and whose get() method will throw an exception upon cancellation
翻译可能不是很准确,大致的意思就是:
创建和执行一个周期性的动作,这个动作在给定的初始时间延迟之后首次使能,并且以给定的时间间隔持续执行。该动作的执行首次发生于initialDelay个时间单位之后,然后是initialDelay+period,initialDelay + 2*period等等。如果定时任务的任何一次执行发生一个异常,后续执行将被停止。如果没有发生任何异常,定时任务将直到线程池执行器终止或取消才终止。如果该定时任务的任何一次执行花费的时间长于它的时间间隔(period),那么后续执行会延迟开始,而不会并行执行。
参数:
command: 待执行的任务。
initialDelay: 初始时间延迟。
period:相邻的执行之间的时间间隔。
unit: 时间单位。
返回值:
一个ScheduledFuture对象,用于表达尚未完成的任务。在任务取消时,其get)方法将抛出一个异常。
任务延迟的情况:
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.scheduleAtFixedRate( new Runnable(){ @Override public void run() { System.out.println("scheduled:" + new Date() + " " + Thread.currentThread().getId()); try { Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } } }, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );
sleep()导致任务发生延迟,此时任务从每秒执行1次变成了每3秒执行1次。
scheduled:Sun Mar 12 20:55:34 CST 2017 8
scheduled:Sun Mar 12 20:55:37 CST 2017 8
scheduled:Sun Mar 12 20:55:40 CST 2017 10
scheduled:Sun Mar 12 20:55:43 CST 2017 10
scheduled:Sun Mar 12 20:55:46 CST 2017 10
scheduled:Sun Mar 12 20:55:49 CST 2017 10
scheduled:Sun Mar 12 20:55:52 CST 2017 10
scheduled:Sun Mar 12 20:55:55 CST 2017 10
1.4. 固定延时的定时器
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.scheduleWithFixedDelay( new Runnable(){ @Override public void run() { System.out.println("scheduled:" + new Date() + " " + Thread.currentThread().getId()); } }, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );
scheduled:Sun Mar 12 20:51:29 CST 2017 8
scheduled:Sun Mar 12 20:51:30 CST 2017 8
scheduled:Sun Mar 12 20:51:31 CST 2017 10
scheduled:Sun Mar 12 20:51:32 CST 2017 10
scheduled:Sun Mar 12 20:51:33 CST 2017 10
scheduled:Sun Mar 12 20:51:34 CST 2017 10
scheduled:Sun Mar 12 20:51:35 CST 2017 10
scheduled:Sun Mar 12 20:51:36 CST 2017 10
scheduled:Sun Mar 12 20:51:37 CST 2017 11
scheduled:Sun Mar 12 20:51:38 CST 2017 11
任务被延迟的情况:
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); executorService.scheduleWithFixedDelay( new Runnable(){ @Override public void run() { System.out.println("scheduled:" + new Date() + " " + Thread.currentThread().getId()); try { Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } } }, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );
原来计划每秒执行1次的任务,变成了每4秒执行1次。后续延时周期跟固定比率定时器有差异。固定比率变成了3秒,而固定延时变成了4秒。
固定比率可以理解为前面任务结束后发现执行时间已经超过了延时间隔周期就不在等待而是立即开始执行后续任务。 固定延时可以理解为前面任务完成之后开始正常计算后续任务的延时。
scheduled:Sun Mar 12 20:35:44 CST 2017 8
scheduled:Sun Mar 12 20:35:48 CST 2017 8
scheduled:Sun Mar 12 20:35:52 CST 2017 10
scheduled:Sun Mar 12 20:35:56 CST 2017 10
scheduled:Sun Mar 12 20:36:00 CST 2017 10
scheduled:Sun Mar 12 20:36:04 CST 2017 10
scheduled:Sun Mar 12 20:36:08 CST 2017 10
scheduled:Sun Mar 12 20:36:12 CST 2017 10
scheduled:Sun Mar 12 20:36:16 CST 2017 10
scheduled:Sun Mar 12 20:36:20 CST 2017 10
scheduled:Sun Mar 12 20:36:24 CST 2017 10
scheduled:Sun Mar 12 20:36:28 CST 2017 10
scheduled:Sun Mar 12 20:36:32 CST 2017 10
scheduled:Sun Mar 12 20:36:36 CST 2017 10
Java并发程序设计(8)线程池之用于定时器