Java ScheduledExecutorService的具體使用
ScheduledExecutorService
有線(xiàn)程池的特性,也可以實(shí)現(xiàn)任務(wù)循環(huán)執(zhí)行,可以看作是一個(gè)簡(jiǎn)單地定時(shí)任務(wù)組件,因?yàn)橛芯€(xiàn)程池特性,所以任務(wù)之間可以多線(xiàn)程并發(fā)執(zhí)行,互不影響,當(dāng)任務(wù)來(lái)的時(shí)候,才會(huì)真正創(chuàng)建線(xiàn)程去執(zhí)行
我們?cè)谧鲆恍┢胀ǘ〞r(shí)循環(huán)任務(wù)時(shí)可以用它,比如定時(shí)刷新字典常量,只需要不斷重復(fù)執(zhí)行即可,這篇文章講解一下它的用法以及注意事項(xiàng),不涉及底層原理
注意:我們都知道,在使用線(xiàn)程池的時(shí)候,如果我們的任務(wù)出現(xiàn)異常沒(méi)有捕獲,那么線(xiàn)程會(huì)銷(xiāo)毀被回收,不會(huì)影響其他任務(wù)繼續(xù)提交并執(zhí)行,但是在這里,如果你的任務(wù)出現(xiàn)異常沒(méi)有捕獲,會(huì)導(dǎo)致后續(xù)的任務(wù)不再執(zhí)行,所以一定要try...catch
1. 延遲不循環(huán)任務(wù)schedule方法
schedule(Runnable command, long delay, TimeUnit unit)
參數(shù)1:任務(wù)
參數(shù)2:方法第一次執(zhí)行的延遲時(shí)間
參數(shù)3:延遲單位
說(shuō)明:延遲任務(wù),只執(zhí)行一次(不會(huì)再次執(zhí)行),參數(shù)2為延遲時(shí)間
案例說(shuō)明:
@Component @Slf4j public class MineExecutors { private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:sss"); @PostConstruct public void init() { scheduler.schedule(() -> { try { log.info("開(kāi)始執(zhí)行...time {}", format.format(new Date())); Thread.sleep(1000); log.info("執(zhí)行結(jié)束...time {}", format.format(new Date())); } catch (Exception e) { log.error("定時(shí)任務(wù)執(zhí)行出錯(cuò)"); } }, 5, TimeUnit.SECONDS); log.info("初始化成功 {}", format.format(new Date())); } }
可以看到任務(wù)執(zhí)行時(shí)間為初始化完成后5s才開(kāi)始執(zhí)行,且只執(zhí)行一次
2. 延遲且循環(huán)cheduleAtFixedRate方法
cheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
參數(shù)1:任務(wù)
參數(shù)2:初始化完成后延遲多長(zhǎng)時(shí)間執(zhí)行第一次任務(wù)
參數(shù)3:任務(wù)時(shí)間間隔
參數(shù)4:?jiǎn)挝?/p>
方法解釋?zhuān)菏且陨弦粋€(gè)任務(wù)開(kāi)始的時(shí)間計(jì)時(shí),比如period
為5,那5秒后,檢測(cè)上一個(gè)任務(wù)是否執(zhí)行完畢,如果上一個(gè)任務(wù)執(zhí)行完畢,則當(dāng)前任務(wù)立即執(zhí)行,如果上一個(gè)任務(wù)沒(méi)有執(zhí)行完畢,則需要等上一個(gè)任務(wù)執(zhí)行完畢后立即執(zhí)行,如果你的任務(wù)執(zhí)行時(shí)間超過(guò)5秒,那么任務(wù)時(shí)間間隔參數(shù)將無(wú)效,任務(wù)會(huì)不停地循環(huán)執(zhí)行,由此可得出該方法不能?chē)?yán)格保證任務(wù)按一定時(shí)間間隔執(zhí)行
錯(cuò)誤:任務(wù)連續(xù)執(zhí)行案例:
@Component @Slf4j public class MineExecutors { private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @PostConstruct public void init() { scheduler.scheduleAtFixedRate(() -> { try { log.info("開(kāi)始執(zhí)行...time {}", format.format(new Date())); Thread.sleep(3000); log.info("執(zhí)行結(jié)束...time {}", format.format(new Date())); } catch (Exception e) { log.error("定時(shí)任務(wù)執(zhí)行出錯(cuò)"); } }, 0, 2, TimeUnit.SECONDS); log.info("初始化成功 {}", format.format(new Date())); } }
由上面代碼可以看出,任務(wù)執(zhí)行需要3秒,而我們?cè)O(shè)定的任務(wù)時(shí)間間隔為2秒,如此就會(huì)導(dǎo)致任務(wù)連續(xù)執(zhí)行,該方法不能?chē)?yán)格保證任務(wù)按照規(guī)定的時(shí)間間隔執(zhí)行,如果你的任務(wù)執(zhí)行時(shí)間可以保證忽略不計(jì),則可以使用該方法,我們可以看到下面日志,上一個(gè)任務(wù)的執(zhí)行結(jié)束時(shí)間與下一個(gè)任務(wù)的開(kāi)始時(shí)間一致,所以任務(wù)連續(xù)循環(huán)執(zhí)行了
正確案例:
@Component @Slf4j public class MineExecutors { private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @PostConstruct public void init() { scheduler.scheduleAtFixedRate(() -> { try { log.info("開(kāi)始執(zhí)行...time {}", format.format(new Date())); Thread.sleep(1000); log.info("執(zhí)行結(jié)束...time {}", format.format(new Date())); } catch (Exception e) { log.error("定時(shí)任務(wù)執(zhí)行出錯(cuò)"); } }, 0, 3, TimeUnit.SECONDS); log.info("初始化成功 {}", format.format(new Date())); } }
可以看到任務(wù)以上一次任務(wù)的開(kāi)始時(shí)間,按3秒一次的方式執(zhí)行
3. 嚴(yán)格按照一定時(shí)間間隔執(zhí)行``
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
參數(shù)1:任務(wù)
參數(shù)2:初始化完成后延遲多長(zhǎng)時(shí)間執(zhí)行第一次任務(wù)
參數(shù)3:任務(wù)執(zhí)行時(shí)間間隔
參數(shù)4:?jiǎn)挝?br />解釋?zhuān)阂陨弦淮稳蝿?wù)執(zhí)行結(jié)束時(shí)間為準(zhǔn),加上任務(wù)時(shí)間間隔作為下一次任務(wù)開(kāi)始時(shí)間,由此可以得出,任務(wù)可以嚴(yán)格按照時(shí)間間隔執(zhí)行
案例:
@Component @Slf4j public class MineExecutors { private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @PostConstruct public void init() { scheduler.scheduleWithFixedDelay(() -> { try { log.info("開(kāi)始執(zhí)行...time {}", format.format(new Date())); Thread.sleep(5000); log.info("執(zhí)行結(jié)束...time {}", format.format(new Date())); } catch (Exception e) { log.error("定時(shí)任務(wù)執(zhí)行出錯(cuò)"); } }, 0, 3, TimeUnit.SECONDS); log.info("初始化成功 {}", format.format(new Date())); } }
由下圖日志可以看出,下次任務(wù)的開(kāi)始時(shí)間是在上一次任務(wù)結(jié)束時(shí)間+任務(wù)時(shí)間間隔為準(zhǔn)的,嚴(yán)格按照任務(wù)時(shí)間間隔,規(guī)律執(zhí)行,如果你的任務(wù)需要保證嚴(yán)格的時(shí)間間隔,可以用該方法啟動(dòng)任務(wù)
其他用法與線(xiàn)程池沒(méi)有差異了,例如ThreadFactory
作為參數(shù)傳入,自定義線(xiàn)程池內(nèi)線(xiàn)程名稱(chēng)之類(lèi)的,不多解釋了。
到此這篇關(guān)于Java ScheduledExecutorService的具體使用的文章就介紹到這了,更多相關(guān)ScheduledExecutorService內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 根據(jù)身份證號(hào)碼判斷出生日期、性別、年齡的示例
這篇文章主要介紹了java 根據(jù)身份證號(hào)碼判斷出生日期、性別、年齡的示例,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-10-10Java通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)一個(gè)簡(jiǎn)單的攔截器操作
這篇文章主要介紹了Java通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)一個(gè)簡(jiǎn)單的攔截器操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java Class 解析器實(shí)現(xiàn)方法示例
這篇文章主要通過(guò)對(duì)class文件的分析,介紹了Java Class 解析器實(shí)現(xiàn)方法示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-09-09初識(shí)Spring Boot框架之Spring Boot的自動(dòng)配置
本篇文章主要介紹了初識(shí)Spring Boot框架之Spring Boot的自動(dòng)配置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04Sentinel結(jié)合Nacos實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解
這篇文章主要介紹了Sentinel結(jié)合Nacos實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程,要持久化的原因是因?yàn)槊看螁?dòng)Sentinel都會(huì)使之前配置的規(guī)則就清空了,這樣每次都要再去設(shè)定規(guī)則顯得非常的麻煩,感興趣想要詳細(xì)了解可以參考下文2023-05-05springboot整合vue實(shí)現(xiàn)上傳下載文件
這篇文章主要為大家詳細(xì)介紹了springboot整合vue實(shí)現(xiàn)上傳下載文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11JavaFX Metro UI 和 開(kāi)發(fā)庫(kù)使用簡(jiǎn)介
這篇文章主要介紹了JavaFX Metro UI 和 開(kāi)發(fā)庫(kù)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08