在《【自省】使用Executors.xxx违反阿里Java代码规范,那还不写定时任务了?》 中仍然通过【自省】的方式讨论了也可以使用 ScheduledExecutorService#scheduleAtFixedRate来实现定时任务,它的运行机制大概是这样:
用 ScheduledExecutorService#scheduleAtFixedRate逻辑看很简单,也很清晰,但任何事情都有两面性,把任务丢给线程池的方式,实现起来自然简单清晰,但肯定也有弊端。如果要把锁的功能做的健壮,总要从不断地自我质疑、自我反思中,理顺思路,寻找答案,我认为这属于自省式学习,以后也想尝试这种模式,一起再看看有啥问题:
boolean lockResult = lockInstance.tryLock();
if(lockResult){
//do work
}finally{
lockInstance.unLock();
}
public interface Future
public static void testCancel() throws InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
System.out.println(" start : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println(" work : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}, 5, 5, TimeUnit.SECONDS);
TimeUnit.SECONDS.sleep(15);
scheduledFuture.cancel(true);
System.out.println("cancel : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
TimeUnit.SECONDS.sleep(30);
}
start : 2022-12-10T19:24:31.508
work : 2022-12-10T19:24:36.538
work : 2022-12-10T19:24:41.539
work : 2022-12-10T19:24:46.541
cancel : 2022-12-10T19:24:46.541 //成功取消
问题:cancel的参数mayInterruptIfRunning 是什么意思?
从父类cancel方法的注释中可以寻找到答案,如果是 true 的话,即代表尝试通过中断的方式来停止任务
If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
问题:那就是说也可能抛出 InterruptedException 了?
public static void testExceptionCatch() throws InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> scheduledFuture = null;
System.out.println(" start : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
try {
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println(" work : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//throw new RuntimeException("");
}, 5, 5, TimeUnit.SECONDS);
}catch (Exception exp){
exp.printStackTrace();
}
TimeUnit.SECONDS.sleep(15);
scheduledFuture.cancel(true);
System.out.println("cancel : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
TimeUnit.SECONDS.sleep(30);
}
结果中的信息 java.lang.InterruptedException: sleep interrupted 可以明确是任务内的逻辑是可通过中断机制实现的。
start : 2022-12-10T20:10:31.248
work : 2022-12-10T20:10:36.276
work : 2022-12-10T20:10:41.272
work : 2022-12-10T20:10:46.277
cancel : 2022-12-10T20:10:46.277
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at com.wushiyii.lock.ScheduleTest.lambda$testExceptionCatch$1(ScheduleTest.java:39)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
问题:之前实例中取消任务时,外部也无异常信息,线程池内部留着这个异常干嘛了呢?
直接抛出异常试试看
public static void testExceptionCatch() throws InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> scheduledFuture = null;
System.out.println(" start : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
try {
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println(" work : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
throw new RuntimeException("just throw ");
//throw new RuntimeException("");
}, 5, 5, TimeUnit.SECONDS);
}catch (Exception exp){
exp.printStackTrace();
}
TimeUnit.SECONDS.sleep(15);
scheduledFuture.cancel(true);
System.out.println("cancel : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
TimeUnit.SECONDS.sleep(30);
}
仔细观察能看出,结果变的有意思了,work只执行了一次,前文中的执行结果中work都执行了3次,这里却只执行了一次。
start : 2022-12-10T20:16:53.285
work : 2022-12-10T20:16:58.307
cancel : 2022-12-10T20:17:08.305
问题:任务内抛出异常能导致定时任务失去定时执行的能力?
是的,使用scheduleAtFixedRate有以下几个情况必须注意:
页面更新:2024-03-30
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号