亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring?scheduled單線程和多線程使用的坑怎么解決

發布時間:2022-02-03 12:30:50 來源:億速云 閱讀:264 作者:iii 欄目:開發技術

本篇內容介紹了“spring scheduled單線程和多線程使用的坑怎么解決”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

公司在使用定時任務的時候,使用的是spring scheduled。

代碼如下:

@EnableScheduling
public class TaskFileScheduleService {


    @Scheduled(cron="0 */1 * * * ?")
    public void task1(){
    .......
    }
    
    @Scheduled(cron="0 */1 * * * ?")
    public void task2(){
    .......
    }

某天,接到領導的電話,說生產環境的定時任務不跑了,趕緊給看看~
做為一名負責人的程序員,趕緊放下手中泡面,遠程到公司的電腦~
線程卡死這種問題,第一步當然是將jvm中的heap dump和thread dump導出來~
經過簡單分析,thread dump中某個線程確實一直處理running狀態,heap dump沒啥問題~
thread dump中的問題線程:

"pool-2-thread-43" #368 prio=5 os_prio=0 tid=0x00005587fd54c800 nid=0x1df runnable [0x00007ff7e2056000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.net.SocketInputStream.read(SocketInputStream.java:224)
    at ch.ethz.ssh3.transport.ClientServerHello.readLineRN(ClientServerHello.java:30)
    at ch.ethz.ssh3.transport.ClientServerHello.<init>(ClientServerHello.java:67)
    at ch.ethz.ssh3.transport.TransportManager.initialize(TransportManager.java:455)
    at ch.ethz.ssh3.Connection.connect(Connection.java:643)
    - locked <0x000000074539e0e8> (a ch.ethz.ssh3.Connection)
    at ch.ethz.ssh3.Connection.connect(Connection.java:490)
    - locked <0x000000074539e0e8> (a ch.ethz.ssh3.Connection)
    at com.suneee.yige.medicalserver.common.SSHUtils.connect(SSHUtils.java:24)
    at com.suneee.yige.medicalserver.service.TaskFileScheduleService.getConn(TaskFileScheduleService.java:102)
    at com.suneee.yige.medicalserver.service.TaskFileScheduleService.taskInfo(TaskFileScheduleService.java:108)
    at com.suneee.yige.medicalserver.service.TaskFileScheduleService.task(TaskFileScheduleService.java:74)
    at sun.reflect.GeneratedMethodAccessor295.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    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)

很明顯,ch.ethz.ssh3.Connection.connect這個方法卡死,導致線程一直處于running狀態。

由于spring scheduled默認是所有定時任務都在一個線程中執行!!這是個大坑!!!
也就是說定時任務1一直在執行,定時任務2一直在等待定時任務1執行完成。這就導致了生產上定時任務全部卡死的現象。

問題已經很明確了,要么解決ch.ethz.ssh3.Connection.connect卡死的問題,要么解決spring scheduled單線程處理的問題。

首先,想到的是處理ch.ethz.ssh3.Connection.connect卡死的問題,但是經過一番查找,發現這個ssh的工具包很久沒更更新過了,也沒有設置例如httpclient的超時時間之類的。這就很難辦了!果斷放棄!!

現在只剩一條路,怎么在任務1卡死的時候,任務2可以按他自己的周期執行,且任務1也按照固定周期執行,不會因為某次任務1卡死導致后續的定時任務出現問題!

方法一:

添加配置

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(50));
    }
}

這個方法,在程序啟動后,會逐步啟動50個線程,放在線程池中。每個定時任務會占用1個線程。但是相同的定時任務,執行的時候,還是在同一個線程中。
例如,程序啟動,每個定時任務占用一個線程。任務1開始執行,任務2也開始執行。如果任務1卡死了,那么下個周期,任務1還是處理卡死狀態,任務2可以正常執行。也就是說,任務1某一次卡死了,不會影響其他線程,但是他自己本身這個定時任務會一直等待上一次任務執行完成!
這種顯然不行!這也是踩過坑才知道的!!!

方法二(正解):

添加配置:

@Configuration
@EnableAsync
public class ScheduleConfig {

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(50);
        return taskScheduler;
    }
}

在方法上添加注解@Async

@EnableScheduling
public class TaskFileScheduleService {


    @Async
    @Scheduled(cron="0 */1 * * * ?")
    public void task1(){
    .......
    }
    
    @Async
    @Scheduled(cron="0 */1 * * * ?")
    public void task2(){
    .......
    }

這種方法,每次定時任務啟動的時候,都會創建一個單獨的線程來處理。也就是說同一個定時任務也會啟動多個線程處理。
例如:任務1和任務2一起處理,但是線程1卡死了,任務2是可以正常執行的。且下個周期,任務1還是會正常執行,不會因為上一次卡死了,影響任務1。
但是任務1中的卡死線程越來越多,會導致50個線程池占滿,還是會影響到定時任務。
這時候,可能會幾個月發生一次~到時候再重啟就行了!

“spring scheduled單線程和多線程使用的坑怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黑河市| 德保县| 合水县| 武义县| 和平县| 岐山县| 临湘市| 集贤县| 济南市| 兖州市| 揭西县| 阳原县| 英山县| 景东| 松原市| 烟台市| 奎屯市| 义马市| 威海市| 新疆| 化隆| 武宣县| 彰化县| 长沙市| 开江县| 彭泽县| 大冶市| 孝昌县| 永定县| 日照市| 缙云县| 太仓市| 溧阳市| 乌兰察布市| 建水县| 石台县| 马公市| 弋阳县| 香港| 玛纳斯县| 尉犁县|