范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

线程池里的定时任务跑的可欢了,可咋停掉特定的任务?

  客户端抢到分布式锁之后开始执行任务,执行完毕后再释放分布式锁。持锁后因客户端异常未能把锁释放,会导致锁成为永恒锁。为了避免这种情况,在创建锁的时候给锁指定一个过期时间。到期之后锁会被自动删除掉,这个角度看是对锁资源的一种保护。重点:但若锁过期被删除后,任务还没结束怎么办?可以通过在一个额外的线程中主动推迟分布式锁的过期时间,下文也用续期一词来表述;避免当任务还没执行完,锁就被删除了。但当分布式锁很多的情况下,每个锁都配置一个线程着实浪费,所以是否可以用线程池里的定时任务呢?
  在《【自省】使用Executors.xxx违反阿里Java代码规范,那还不写定时任务了?》 中仍然通过【自省】的方式讨论了也可以使用 ScheduledExecutorService#scheduleAtFixedRate来实现定时任务,它的运行机制大概是这样:如果上一个任务的执行时间大于等待时间,任务结束后,下一个任务马上执行。如果上一个任务的执行时间小于等待时间,任务结束后,下一个任务在(间隔时间-执行时间)后开始执行。二、理还乱?
  用 ScheduledExecutorService#scheduleAtFixedRate逻辑看很简单,也很清晰,但任何事情都有两面性,把任务丢给线程池的方式,实现起来自然简单清晰,但肯定也有弊端。如果要把锁的功能做的健壮,总要从不断地自我质疑、自我反思中,理顺思路,寻找答案,我认为这属于自省式学习,以后也想尝试这种模式,一起再看看有啥问题:问题:锁主动释放的时候,续期的任务要关闭嘛?是的,当锁被用户主动关闭的时候,主动续期的任务是要主动取消掉的。问题:如果我不主动取消呢?对于不主动续期的锁,抢锁后配置一个合适的过期时间,到期之后锁自然会被释放;这种情况下,客户端本就没有续期任务需要取消。但如果有额外的线程|线程池在定时续期的话,锁用完了需要被释放掉,任务一定要主动取消掉。问题:可万一忘记了呢?有加锁解锁的代码模板,按照模板来;获取锁之后,在finally中执行释放锁的操作。boolean lockResult = lockInstance.tryLock();  if(lockResult){     //do work }finally{     lockInstance.unLock(); }万一程序异常崩了,没执行finally呢?如果程序异常崩了,进程消失后,进程内的资源自然就都释放掉了:续期任务没有了,续期的线程|线程池也没有了。但锁资源就需要依赖锁服务,如 Redis ,在锁过期后主动释放掉锁资源。问题:关于停止任务,在前文独立线程的实现方式中,有介绍可通过中断机制;但是线程池里的任务怎么取消呢?遇事不决问百度,排名第一必有解
  咱得本意是取消一个任务,示例给出的方法是要把线程池关掉。
  问题:取消一个任务,要把整个线程池都关掉?按照示例所给的办法是不行的,每个任务的取消,都要关闭整个线程池的话,若给每个任务都配有独立的取消能力,就需要给每个任务都配一个独立的线程池,这就跟每个锁配一个独立的线程没有区别了。
  问题:目标是多个任务共享一个线程池,怎么不关闭线程池而只关闭特定的任务呢?百度出来跟问题相关的文章本就不多,而多数文章提供的奇思妙招并不好使,笔者是浪费了一些时间的,但不能再耽误读者朋友的时间,直接给思路:解铃还须系铃人,scheduleAtFixedRate的返回值是是ScheduledFuture。
  问题:看到 xxxFuture 是否想能想起Future接口的能力?猜测熟悉 get()方法的同学应该特别多,但不知道熟不熟悉cancel方法,如果看到这个方法感到惊喜,欢迎留言互动。
  public interface Future { boolean cancel(boolean mayInterruptIfRunning); ... V get() throws InterruptedException, ExecutionException; ... } 复制代码问题:cancel方法好使嘛?不看理论看实效果,试试看: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 里都做了什么呢?看源码可知,其内有两层核心逻辑:尝试取消正在执行的任务避免任务再被定时执行
  三、新的思考
  问题: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 了?如果是抛出 InterruptedException ,示例中,并未看到程序测试有异常中断,也未看到有异常日志信息。问题:怎么有点玄学了,还能不是interrupt机制?在任务内尝试捕获一下看看: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有以下几个情况必须注意:任务逻辑中未捕获的异常能导致本该定时执行的任务,后续不再执行。任务逻辑中未捕获的异常不会外抛,外部感知不到。任务逻辑中的异常,需在任务逻辑内捕获并记录,否则无处可知。

北京慢生活的一天图片来自网络北京的生活节奏虽然不像上海深圳那么快,但相比全国多数非沿海城市,节奏还是偏快的,但就是在这样一个全国的政治经济文化中心出差时,我竟然无意中过了一个慢生活的工作日。缘悭一免费公园本文将占用您5分钟的阅读时间但会回报您10分的精彩摄文竹说起京城夏季赏荷,咱们介绍过城区的各家市属公园,也介绍过以颐和园圆明园为首的北边几大公园,那么,城南有什么赏花赏荷游玩消夏的神奇动物在哪里?带娃到这些地方一探究竟吧孩子们与动物之间有着一种奇妙的联系也许是因为纯真和天然本为一体两者同框往往会给人以温暖趁着暑期带上孩子一起去寻找神奇动物吧!北京动物园北京动物园始建于1906年,在西直门外乐善园继周末去怀柔,包个小院玩水过夏天带娃去哪儿玩群里有真正的驴友每周末都带孩子爬山,且野山居多,但也有懒人喜欢在周末约上朋友住民宿吃吃喝喝,打麻将唱唱歌再玩几把狼人杀,孩子们在一旁玩玩水,好不惬意。上周末我就懒了一回夜京城玩出新花样!这里逛夜市,周周有不同北京日报客户端记者马婧潮流艺术营地趣玩烟火生活近日,中粮祥云小镇开启夜间主题活动祥云夕街夜市集,每当夜幕降临,长达300米的落日夕街热闹起来。活动将一直延续到中秋假日,长达6周的时玉钦居士我在青城山修行的那些日子我回想起自己31岁时,前往道教青城山拜访修行的日子,那段经历回想起来就像昨天才发生的事情一样。踏上这座神山的那一刻,感觉自己的心灵仿佛都被它庄重祥和的气息所洗涤。在那里没有城市的喧世界动物保护协会全球超七成游客对战利品狩猎说不2022年8月10日,正值世界狮子日,世界动物保护协会发布最新研究,发现全球超过七成的游客希望禁止战利品狩猎,支持野生动物友好型旅游,保护受到旅游娱乐业影响的野生动物。该调研数据源中英直航终于开通普大喜奔!国航恢复中英间直航航班!其他航司的往返直航也快了!国航公布英国和中国之间的往返直飞航线,目前开放一个航班,9月17日首趟伦敦希斯罗上海浦东,11月前每周六飞,航班号CA8太好了!望京新开一公园,景观别致,就在这儿每天给大家带来望京最新消息的小编,今天有一个好消息要与大家分享,咱望京又新添一座街心公园,景观别致非常有特色。这座精致的公园究竟是何面貌,一起来看热心网友在咱邻友圈APP上的发帖分排面拉满!江苏中天董事长致贺词祝福张常宁,郎平搭档摸宝宝的脸中国女排国家队在结束了前段时间的世界女排联赛之后,一直在国内进行封闭性训练,中国女排的目标非常明确,那就是即将开始的世界女排锦标赛。世界女排锦标赛,四年才举办一次,对于中国女排来说8月初周末的无蚊公园活水公园位于成都市内的府河边,是世界上第一座城市的综合性环境教育公园。从1997年春天破土动工,工程初步完成,投资达3000万元人民币。活水公园2022年7月29日正式开园门票免费
孩子便秘,开塞露不见效,分享一个小方子,只有3味药,润肠通便6岁的安安(化名)总是便秘,大便又干又硬,多喝水开塞露都没用。妈妈愁坏了,找中医开了个方子,只有三味药,喝了一周,便便就软化了,排便困难明显缓解,今天我就来解读一下这个方子小承气汤如果婴儿期的喂养是一场考核,你达标了吗?育儿的起跑线到底在哪里?人与人之间到底是什么时候被拉开距离的?可能比你想象的还要早。其实这个答案最早可以追溯到生命最初的1000天。世界卫生组织将宝宝从怀胎10月的280天到宝宝出22年12月7日星期三一位带我见识家庭教育的姐姐曾分享过一篇文章,虽然知识和认识有限,但是当时一段话让我印象深刻。说现在有些北京高知父母,放弃北京很珍贵的学位,在北京周边建了一所学校,用自己的方式,教孩让孩子爱上学习(三)儿童注意力的特点家长百问百答上一次我们谈到需要结合孩子的兴趣来抓住TA对学习的注意力,但让很多家长头疼的是,孩子注意力总是不集中,哪怕一时吸引了注意,TA很快就厌倦了。今天我们就来谈谈儿童注意力的二胎隔1年好还是隔3年好?区别不是一点点看着自己超级萌又有点调皮的孩子一天天长大,爸爸妈妈们或许都畅想过要不要再生一个宝宝呀,或者正计划着再要一个。不过妈妈到底间隔多久怀二胎,对自己和小宝宝健康比较好呢?老大和老二相差几师生矛盾频上热搜,背后究竟存在哪些问题?如今社会上有一种矛盾,就是老师与学生之间的矛盾,或者也可以说是家长与老师之间的矛盾。从某些幼儿园虐待儿童到中小学教师体罚学生,再到高校学生与老师之间的冲突这些案例无一不牵动着家长的天边榜单新十条之后第一站去哪儿?衡山雾凇赏雪正当时12月7日,国务院联防联控机制发布关于进一步优化落实疫情防控的通知,不再对跨地区流动人员查验核酸检测阴性证明和健康码。这一消息无疑是对旅游业的利好,消息发布后,各旅游平台机票等产品云南贡山县独龙江乡旅游独龙江乡,是云南旅游的最后秘境,几十年来,不为外人所知,它比欧美旅游还稀奇,你再有钱也不一定能去独龙江乡旅游,因为它经常不定时关闭。独龙江,流经察隅县贡山县缅甸克钦邦,也是横断山脉当冬日阴雨遇上秋霞圃入冬以来,上海这几天体感温度较低,但并没有阻挡嘉定市民感知季节变换的脚步。不少人在阴雨绵绵中,外出探寻与冬日美景的第一场邂逅。在秋霞圃,冬日之景呈现在这座古典园林的各个角落。石砖路运城城区公共文化场所全部开放全市文旅类市场主体正全面有序复工复产运城市市区范围内文化馆博物馆河东书房等公共文化场所已全面恢复免费开放全市27家A级景区已实现恢复开放全市经营性文化娱乐场所正在全面有序地恢复营业为助力全市恢复生产生活秩序,运城市文贵州男子隐居深山住20年,本以为一贫如洗,出山后却成亿万富翁在贵州省贵安新区党武乡有一座名为夜郎谷喀斯特生态园的3A级旅游景点,这里怪石嶙峋,有数条瀑布悬崖险滩,还有无数石雕艺术品堆砌如城堡。如今到处都在搞旅游资源开发,这一小小景点似乎不足