ScheduledExecutorService是java.util.concurrent并发包下的一个接口,表示调度服务~,它定义了以下几个方法:
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit); public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
前2个的任务是指定在延迟时间后执行一次任务,后2个方法则表示每间隔一段时间定时执行任务。
ScheduledExecutorService的后两个方法比较容易搞混,下面就用小例子来搞清楚:
public class DiffTest { private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); public static void main(String[] args) { final long executeTime = (long) (Math.random()*10); //scheduleAtFixedRate executor.scheduleAtFixedRate(new Runnable(){ //模拟耗时任务,耗时是10s以内的任意数 @Override public void run() { try { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); System.out.print(sdf.format(new Date()) + " 开始执行, "); Thread.sleep(3000);//3s System.out.println(sdf.format(new Date()) + "结束执行 ================"); } catch (InterruptedException e) { e.printStackTrace(); } } }, 0, 5, TimeUnit.SECONDS);//每隔5s } }
当间隔时间(5s)大于任务的执行时间(3s),运行结果为:
12:00:03 开始执行, 12:00:06结束执行 ================
12:00:08 开始执行, 12:00:11结束执行 ================
12:00:13 开始执行, 12:00:16结束执行 ================
12:00:18 开始执行, 12:00:21结束执行 ================
12:00:23 开始执行, 12:00:26结束执行 ================
12:00:28 开始执行, 12:00:31结束执行 ================
当间隔时间(5s)小于程序(7s)执行时间(将耗时改为7s, 每隔5s的设置就会失效)
12:01:26 开始执行, 12:01:33结束执行 ================
12:01:33 开始执行, 12:01:40结束执行 ================
12:01:40 开始执行, 12:01:47结束执行 ================
12:01:47 开始执行, 12:01:54结束执行 ================
12:01:54 开始执行, 12:02:01结束执行 ================
12:02:01 开始执行, 12:02:08结束执行 ================
说明:scheduleAtFixedRate是以上一次任务的开始时间为间隔的,并且当任务执行时间大于设置的间隔时间时,真正间隔的时间由任务执行时间为准!
再来测试下scheduleWithFixedDelay:
executor.scheduleWithFixedDelay(new Runnable(){ //模拟耗时任务,耗时是10s以内的任意数 @Override public void run() { try { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); System.out.print(sdf.format(new Date()) + " 开始执行, "); Thread.sleep(3000);//3s System.out.println(sdf.format(new Date()) + "结束执行 ================"); } catch (InterruptedException e) { e.printStackTrace(); } } }, 0, 5, TimeUnit.SECONDS);//每隔5s
当间隔时间(5s)大于任务的执行时间(3s),运行结果为:
12:46:54 开始执行, 12:46:57结束执行 ================
12:47:02 开始执行, 12:47:05结束执行 ================
12:47:10 开始执行, 12:47:13结束执行 ================
12:47:18 开始执行, 12:47:21结束执行 ================
12:47:26 开始执行, 12:47:29结束执行 ================
12:47:34 开始执行, 12:47:37结束执行 ================
当间隔时间(5s)小于程序(7s)执行时间,此时运行结果为:
12:48:12 开始执行, 12:48:19结束执行 ================
12:48:24 开始执行, 12:48:31结束执行 ================
12:48:36 开始执行, 12:48:43结束执行 ================
12:48:48 开始执行, 12:48:55结束执行 ================
12:49:00 开始执行, 12:49:07结束执行 ================
12:49:12 开始执行, 12:49:19结束执行 ================
说明:scheduleWithFixedDelay是以上一次任务的结束时间为间隔的!
顺便说下,当定时调度遇到异常时,是否会影响下次任务的执行:
public class DiffTest { private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private static int a; private static int[] aa = {1,2,3}; public static void main(String[] args) { //scheduleAtFixedRate executor.scheduleWithFixedDelay(new Runnable(){ //模拟耗时任务,耗时是10s以内的任意数 @Override public void run() { try { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); System.out.println(sdf.format(new Date()) + " 开始执行"); System.out.println("执行结果:" + aa[a++]); System.out.println("=============="); } catch (Exception e) { e.printStackTrace(); } } }, 0, 5, TimeUnit.SECONDS);//每隔5s } }
运行之,结果为:
19:13:07 开始执行
执行结果:1
==============
19:13:12 开始执行
执行结果:2
==============
19:13:17 开始执行
执行结果:3
==============
19:13:22 开始执行
java.lang.ArrayIndexOutOfBoundsException: 3
at com.nineclient.echat.plugin.DiffTest$1.run(DiffTest.java:28)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
19:13:27 开始执行
java.lang.ArrayIndexOutOfBoundsException: 4
at com.nineclient.echat.plugin.DiffTest$1.run(DiffTest.java:28)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
这说明,虽然执行到第4次时发生了异常,但并不影响下一次的执行。但如果你没有异常捕获机制,则会影响,比如改成:
executor.scheduleWithFixedDelay(new Runnable(){ //模拟耗时任务,耗时是10s以内的任意数 @Override public void run() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); System.out.println(sdf.format(new Date()) + " 开始执行"); System.out.println("执行结果:" + aa[a++]); System.out.println("=============="); } }, 0, 5, TimeUnit.SECONDS);//每隔5s
运行结果为:
19:14:39 开始执行
执行结果:1
==============
19:14:44 开始执行
执行结果:2
==============
19:14:49 开始执行
执行结果:3
==============
19:14:54 开始执行
之后就不再运行了。。所以务必在被调度的任务上加上异常捕获!
相关推荐
下面小编就为大家带来一篇基于ScheduledExecutorService的两种方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
定时器小例子,这是一个经较好定时器应用
这是一个jar,很秀。自定义的一个Java定时器工具类。主要是结合Spring Boot一起使用,并在Spring Boot启动的时候一起启动运行。
主要介绍了ScheduledExecutorService任务定时代码示例,具有一定借鉴价值,需要的朋友可以参考下
ScheduledExecutorService 计时器任务处理,用于超时处理。
调度可以用 Timer 【调用 schedule() 或者 scheduleAtFixedRate() 方法实现】或者 ScheduledExecutorService 【结合工作中其它的需求,笔者选用此】 ScheduledExecutorService的初始化(线程池):
您可以在工作线程上运行任务(Runnable或Callable),以指定执行计划(如ScheduledExecutorService),并指定执行时间。 介面 ScheduledFuture<?> schedule( Runnable command, int executeTime, long delay,...
Springmvc java注解设置定时任务实例,利用 ScheduledExecutorService 接口实现
串行执行器服务 ScheduledExecutorService 的测试实用程序实现 允许测试如下代码: ... service.scheduleAtFixedRate(new Runnable() { @Override public void run() { count++; bar.doWhatever(); } },
Java通用任务执行程序,基于java.util.concurrent.ScheduledExecutorService。 Java通用的任务执行器,基于java.util.concurrent.ScheduledExecutorService工具类实现。 Maven: <groupId>...
springMVC配置、注解、列子
看完《think in java》多线程章节,自己写的多线程文档,还结合了其他的相关网络资料。 线程 一....1)为什么要使用线程池 2 2)一个具有线程池的工作队列 3 ...1)ReentrantLock和synchronized关键字的区别 41
1、使用线程的经验:设置...8、定时器: ScheduledExecutorService、大规模定时器TimerWheel 9、并发三大定律:Amdahl、Gustafson、Sun-Ni 10、神人和图书、相关网络资源 11、业界发展情况: GPGPU、OpenCL 12、复习题
Java多线程入阶干货分享 1.使用线程的经验:设置名称、响应中断、使用ThreadLocal 2.Executor:ExecutorService和...8.定时器:ScheduledExecutorService、大规模定时器TimerWheel 9.并发三大定律 10.图书、相关网络资源
内容列表 1、使用线程的经验:设置名称、...8、定时器: ScheduledExecutorService、大规模定时器TimerWheel 9、并发三大定律:Amdahl、Gustafson、Sun-Ni 10、神人和图书 11、业界发展情况: GPGPU、OpenCL 12、复习题
1、使用线程的经验:设置名称、响应中断、...8、定时器: ScheduledExecutorService、大规模定时器TimerWheel 9、并发三大定律:Amdahl、Gustafson、Sun-Ni 10、神人和图书 11、业界发展情况: GPGPU、OpenCL 12、复习题
scheduledExecutorService.scheduleAtFixedRate(new ScrollTask(), 1,2, TimeUnit.SECONDS); super.onStart(); } @Override protected void onStop() { //当Activity不可见的时候停止切换 ...
线程池执行者 ThreadPoolExecutor,定时执行者服务 ScheduledExecutorService, 使用 ForkJoinPool 进行分叉和合并,锁 Lock,读写锁 ReadWriteLock 原子性长整型 AtomicLong,原子性引用型 AtomicReference 修改数据:...
以下文章基本上保证真实可信,如有谬误欢迎指正; 同时很多内容来自个人有道笔记的摘抄,如果有不清不楚的地方还请见谅,可留言...以及java为我们提供常用的线程池和任务调度ScheduledExecutorService以及工作窃取For