ScheduledExecutorService定时周期执行指定的任务 ,关于scheduleAtFixedRate 和 scheduleWithFixedDelay使用区别
来源:互联网 发布:个人域名申请 编辑:程序博客网 时间:2024/05/19 02:40
在项目中使用到了多线程定时执行指定任务中发现以下一些问题:
/** * 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 * 必须在指定任务完成之后开始。 * {@code initialDelay} then {@code initialDelay+period}, then * {@code 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. * * @param command the task to execute * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null * @throws IllegalArgumentException if period less than or equal to zero */ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);command:执行线程initialDelay:初始化延时period:两次开始执行最小间隔时间unit:计时单位对于scheduleAtFixedRate方法,当我们要执行的任务大于我们指定的执行间隔时会怎么样呢?对于中文API中的注释,我们可能会被忽悠,认为无论怎么样,它都会按照我们指定的间隔进行执行,其实当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务。而是等待该线程执行完毕。 /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the * 创建并执行一个在给定的初始延迟之后才启用的周期操作,然后,在一个执行的终止和下一个执行之间的延迟 * given delay between the termination of one execution and the * commencement of the next. 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. *如果任务的任何执行遇到异常,则会抑制随后的执行。否则,任务将仅通过执行程序的取消或终止而终止。 * @param command the task to execute * @param initialDelay the time to delay first execution * @param delay the delay between the termination of one * execution and the commencement of the next * @param unit the time unit of the initialDelay and delay parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null * @throws IllegalArgumentException if delay less than or equal to zero */ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);command:执行线程initialDelay:初始化延时period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)unit:计时单位这个是以delay为固定延迟时间,按照一定的等待时间来执行任务,initialDelay意义与上面的相同。如果执行初始化延时为0秒,间隔2秒,如果执行任务用了10秒,那下个任务开始就是第12秒后开始执行。这个是优先保证任务执行的间隔。
以上是源码介绍,翻译不好,希望大家指出。
这里用三个定时任务说明下问题,到时根据自己需求制定初时时间、间隔时间、以及线程任务数。
package com;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/** * * @author ZL * 2017年8月29日 */public class Schedule { private static ScheduledExecutorService excutor = Executors.newSingleThreadScheduledExecutor(); /** * scheduleAtFixedRate * 按指定频率周期执行某个任务 <br> * 初始化延迟0ms开始执行,每隔2ms重新执行一次任务。 */ public void one() { excutor.scheduleAtFixedRate(new EchoServerone(), // 执行线程 0, // 初始化延迟 2000, // 两次开始的执行的最小时间间隔 TimeUnit.MILLISECONDS // 计时单位 ); } /** * scheduleAtFixedRate * 按指定频率周期执行某个任务 <br> * 初始化延迟0ms开始执行,每隔2ms重新执行一次任务。 */ public void two() { excutor.scheduleAtFixedRate(new EchoServertwo(), // 执行线程 0, // 初始化延迟 2000, // 两次开始的执行的最小时间间隔 TimeUnit.MILLISECONDS // 计时单位 ); } /** * scheduleWithFixedDelay * 按指定频率周期执行某个任务 <br> * 初始化延迟0ms开始执行,每隔2ms重新执行一次任务。 */ public void three() { excutor.scheduleWithFixedDelay(new EchoServerthree(), // 执行线程 0, // 初始化延迟 2000, // 前一次执行结束到下一次执行开始的间隔时间 TimeUnit.MILLISECONDS); } public static void main(String[] args) { Schedule schedule = new Schedule(); schedule.one(); schedule.two(); schedule.three(); }}
package com;/** * 线程任务一 * @author ZL * 2017年8月29日 */public class EchoServerone implements Runnable { @Override public void run() { System.out.println("线程任务一开始执行"+DateUtils.getnewTime()); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程任务一执行结束"+DateUtils.getnewTime()); }}
package com;/** * 线程任务二 * @author ZL * 2017年8月29日 */public class EchoServertwo implements Runnable { @Override public void run() { System.out.println("线程任务二开始执行"+DateUtils.getnewTime()); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程任务二 执行结束"+DateUtils.getnewTime()); }}
package com;/** * 线程任务三 * @author ZL * 2017年8月29日 */public class EchoServerthree implements Runnable { @Override public void run() { System.out.println("线程任务三开始执行"+DateUtils.getnewTime()); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程任务三执行结束"+DateUtils.getnewTime()); }}
运行结果:
线程任务一开始执行2017-08-29 17:07:25线程任务一执行结束2017-08-29 17:07:35线程任务二开始执行2017-08-29 17:07:35线程任务二 执行结束2017-08-29 17:07:45线程任务三开始执行2017-08-29 17:07:45线程任务三执行结束2017-08-29 17:07:55线程任务一开始执行2017-08-29 17:07:55线程任务一执行结束2017-08-29 17:08:05线程任务二开始执行2017-08-29 17:08:05线程任务二 执行结束2017-08-29 17:08:15线程任务一开始执行2017-08-29 17:08:15线程任务一执行结束2017-08-29 17:08:25线程任务二开始执行2017-08-29 17:08:25线程任务二 执行结束2017-08-29 17:08:35线程任务一开始执行2017-08-29 17:08:35线程任务一执行结束2017-08-29 17:08:45线程任务二开始执行2017-08-29 17:08:45线程任务二 执行结束2017-08-29 17:08:55线程任务一开始执行2017-08-29 17:08:55
看到运行结果肯定会发现,定时任务三只在初次运行时执行后由于每个线程执行中都会有10秒的休眠,,然后定时任务三就不运行了,三个定时任务的间隔时间都为两秒。
解决办法是:
修改的代码:
/*** 把scheduleWithFixedDelay换成scheduleAtFixedRate * 按指定频率周期执行某个任务 <br> * 初始化延迟0ms开始执行,每隔2ms重新执行一次任务。 */ public void three() { excutor.scheduleAtFixedRate(new EchoServerthree(), // 执行线程 0, // 初始化延迟 2000, // 前一次执行结束到下一次执行开始的间隔时间 TimeUnit.MILLISECONDS); }
运行结果:
线程任务一开始执行2017-08-29 17:29:01线程任务一执行结束2017-08-29 17:29:11线程任务二开始执行2017-08-29 17:29:11线程任务二 执行结束2017-08-29 17:29:21线程任务三开始执行2017-08-29 17:29:21线程任务三执行结束2017-08-29 17:29:31线程任务一开始执行2017-08-29 17:29:31线程任务一执行结束2017-08-29 17:29:41线程任务二开始执行2017-08-29 17:29:41线程任务二 执行结束2017-08-29 17:29:51线程任务三开始执行2017-08-29 17:29:51线程任务三执行结束2017-08-29 17:30:01线程任务一开始执行2017-08-29 17:30:01线程任务一执行结束2017-08-29 17:30:11线程任务二开始执行2017-08-29 17:30:11线程任务二 执行结束2017-08-29 17:30:21线程任务三开始执行2017-08-29 17:30:21线程任务三执行结束2017-08-29 17:30:31线程任务一开始执行2017-08-29 17:30:31线程任务一执行结束2017-08-29 17:30:41线程任务二开始执行2017-08-29 17:30:41线程任务二 执行结束2017-08-29 17:30:51
这样运行后的结果就不会出现有线程任务不执行的后果了。需要那种根据自己需求吧。
阅读全文
0 0
- ScheduledExecutorService定时周期执行指定的任务 ,关于scheduleAtFixedRate 和 scheduleWithFixedDelay使用区别
- ScheduledExecutorService 定时任务,scheduleAtFixedRate和scheduleWithFixedDelay区别
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService 定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- ScheduledExecutorService定时周期执行指定的任务
- Java实现邮件发送(带附件)
- 欢迎使用CSDN-markdown编辑器
- 轻装上阵Html5游戏开发,JEESJS(二)
- 自动代码生成的Java Code Template
- Tomcat运行时,发生磁盘空间不足,无法处理此命令
- ScheduledExecutorService定时周期执行指定的任务 ,关于scheduleAtFixedRate 和 scheduleWithFixedDelay使用区别
- 操作系统-面试题/进程与线程
- Win10取消密码
- 算法系列——数组中只出现一次的数字
- 计算机网络名词
- Git 里面的 origin 到底代表啥意思?
- ASP.NET Repeater实现全选反选(原生JS)
- Tomcat溢出问题Exception in thread "http-apr-8080-exec-8" java.lang.OutOfMemoryError: PermGen space
- 使用SSM时的对象管理问题