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

溫馨提示×

溫馨提示×

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

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

SpringBoot中定時任務@Scheduled的多線程如何使用

發布時間:2023-05-06 15:42:54 來源:億速云 閱讀:84 作者:iii 欄目:開發技術

這篇文章主要講解了“SpringBoot中定時任務@Scheduled的多線程如何使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“SpringBoot中定時任務@Scheduled的多線程如何使用”吧!

    一、@Scheduled注解簡介

    @Scheduled是Spring框架中的一個注解,它可以用于配置定時任務,使得方法可以按照規定的時間間隔定時執行。在使用該注解時,我們可以指定任務的執行時間、循環周期、并發數等參數,從而實現定時任務的功能。在Spring Boot中,@Scheduled注解可以直接應用于方法上。

    二、@Scheduled的多線程機制

    在Spring Boot中,@Scheduled注解是基f于Java的ThreadPoolExecutor和ScheduledThreadPoolExecutor實現的。當我們配置了一個定時任務后,Spring Boot會首先創建一個ScheduledThreadPoolExecutor線程池,并將定時任務添加到該線程池中等待執行。然后,在指定的時間到來之后,線程池會為該定時任務分配一個線程來執行。如果該定時任務還未執行完畢,在下一個周期到達時,線程池會為該任務再次分配一個線程來執行。通過這種方式,@Scheduled可以非常方便地實現周期性的定時任務f于Java的ThreadPoolExecutor和ScheduledThreadPoolExecutor實現的。當我們配置了一個定時任務后,Spring Boot會首先創建一個ScheduledThreadPoolExecutor線程池,并將定時任務添加到該線程池中等待執行。然后,在指定的時間到來之后,線程池會為該定時任務分配一個線程來執行。如果該定時任務還未執行完畢,在下一個周期到達時,線程池會為該任務再次分配一個線程來執行。通過這種方式,@Scheduled可以非常方便地實現周期性的定時任務。

    三、@Scheduled的多線程問題

    雖然@Scheduled注解非常便捷,但是它也存在一些多線程的問題,主要體現在以下兩個方面:

    1.定時任務未執行完畢時,后續任務可能會受到影響

    在使用@Scheduled注解時,我們很容易忽略一個問題:如果定時任務在執行時,下一個周期的任務已經到了,那么后續任務可能會受到影響。例如,我們定義了一個間隔時間為5秒的定時任務A,在第1秒時開始執行,需要執行10秒鐘。在第6秒時,定時任務A還沒有結束,此時下一個周期的任務B已經開始等待執行。如果此時線程池中沒有足夠的空閑線程,那么定時任務B就會被阻塞,無法執行。

    2.多個定時任務并發執行可能導致資源競爭

    在某些情況下,我們可能需要編寫多個定時任務,這些定時任務可能涉及到共享資源,例如數據庫連接、緩存對象等。當多個定時任務同時執行時,就會存在資源競爭的問題,可能會導致數據錯誤或者系統崩潰。

    四、@Scheduled加入線程池來處理定時任務

    為了避免上述問題,可以將@Scheduled任務交給線程池進行處理。在Spring Boot中,可以通過以下兩種方式來將@Scheduled任務加入線程池:

    1.使用@EnableScheduling + @Configuration配置ThreadPoolTaskScheduler

    @Configuration
    @EnableScheduling
    public class TaskSchedulerConfig {
        @Bean
        public TaskScheduler taskScheduler() {
            ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
            scheduler.setPoolSize(10);
            scheduler.initialize();
            return scheduler;
        }
    }

    在上述代碼中,我們通過配置ThreadPoolTaskScheduler來創建一個線程池,并使用@EnableScheduling注解將定時任務開啟。其中,setPoolSize方法可以設置線程池的大小,默認為1。

    2.使用ThreadPoolTaskExecutor

    @Configuration
    @EnableScheduling
    public class TaskExecutorConfig {
        @Bean
        public ThreadPoolTaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(10);
            executor.setMaxPoolSize(50);
            executor.setQueueCapacity(1000);
            executor.setKeepAliveSeconds(60);
            executor.setThreadNamePrefix("task-executor-");
            return executor;
        }
    }

    在上述代碼中,我們通過配置ThreadPoolTaskExecutor來創建一個線程池,并使用@EnableScheduling注解將定時任務開啟。其中setCorePoolSize、setMaxPoolSize、setQueueCapacity、setKeepAliveSeconds等方法可以用于配置線程池的大小和任務隊列等參數。

    五、@Scheduled詳細分析

    在Spring Boot中,@Scheduled注解是基于Java的ThreadPoolExecutor和ScheduledThreadPoolExecutor實現的。當我們配置了一個定時任務后,Spring Boot會首先創建一個ScheduledThreadPoolExecutor線程池,并將定時任務添加到該線程池中等待執行。然后,在指定的時間到來之后,線程池會為該定時任務分配一個線程來執行。如果該定時任務還未執行完畢,在下一個周期到達時,線程池會為該任務再次分配一個線程來執行。通過這種方式,@Scheduled可以非常方便地實現周期性的定時任務。

    雖然@Scheduled注解非常便捷,但是它也存在一些多線程的問題,主要體現在以下兩個方面:

    1. 定時任務未執行完畢時,后續任務可能會受到影響

    在使用@Scheduled注解時,我們很容易忽略一個問題:如果定時任務在執行時,下一個周期的任務已經到了,那么后續任務可能會受到影響。例如,我們定義了一個間隔時間為5秒的定時任務A,在第1秒時開始執行,需要執行10秒鐘。在第6秒時,定時任務A還沒有結束,此時下一個周期的任務B已經開始等待執行。如果此時線程池中沒有足夠的空閑線程,那么定時任務B就會被阻塞,無法執行。

    解決方案:

    針對上述問題,我們可以采用以下兩種方案來解決:

    方案一:修改線程池大小

    為了避免因為線程池中線程數量不足引起的問題,我們可以對線程池進行配置,提高線程池的大小,從而確保有足夠的空閑線程來處理定時任務。

    例如,我們可以在application.properties或application.yml或者使用@EnableScheduling + @Configuration來配置線程池大小:

    spring.task.scheduling.pool.size=20

    2. 多個定時任務并發執行可能導致資源競爭

    在某些情況下,我們可能需要編寫多個定時任務,這些定時任務可能涉及到共享資源,例如數據庫連接、緩存對象等。當多個定時任務同時執行時,就會存在資源競爭的問題,可能會導致數據錯誤或者系統崩潰。

    解決方案:

    為了避免由于多個定時任務并發執行導致的資源競爭問題,我們可以采用以下兩種方案來解決:

    方案一:使用鎖機制

    鎖機制是一種常見的解決多線程并發訪問共享資源的方式。在Java中,我們可以使用synchronized關鍵字或者Lock接口來實現鎖機制。

    例如,下面是一個使用synchronized關鍵字實現鎖機制的示例:

    private static Object lockObj = new Object();
    
    @Scheduled(fixedDelay = 1000)
    public void doSomething(){
        synchronized(lockObj){
            // 定時任務要執行的內容
        }
    }

    在上述代碼中,我們定義了一個靜態對象lockObj,用來保護共享資源。在定時任務執行時,我們使用synchronized關鍵字對lockObj進行加鎖,從而確保多個定時任務不能同時訪問共享資源。

    方案二:使用分布式鎖

    除了使用傳統的鎖機制外,還可以使用分布式鎖來解決資源競爭問題。分布式鎖是一種基于分布式系統的鎖機制,它可以不依賴于單個JVM實例,從而能夠保證多個定時任務之間的資源訪問不會沖突。

    在Java開發中,我們可以使用ZooKeeper、Redis等分布式系統來實現分布式鎖機制。例如,使用Redis實現分布式鎖的示例代碼如下:

    @Autowired
    private RedisTemplate redisTemplate;
    
    @Scheduled(fixedDelay = 1000)
    public void doSomething(){
        String lockKey = "lock:key";
        String value = UUID.randomUUID().toString();
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, value, 5L, TimeUnit.SECONDS);
        if(result){
            try{
                // 定時任務要執行的內容
            }finally{
                redisTemplate.delete(lockKey);
            }
        }
    }

    在上述代碼中,我們使用Redis實現了分布式鎖機制。具體而言,我們在定時任務執行時,首先向Redis中寫入一個鍵值對,然后檢查是否成功寫入。如果成功寫入,則表示當前定時任務獲得了鎖,可以執行接下來的操作。在定時任務執行完畢后,我們再從Redis中刪除該鍵值對,釋放鎖資源。

    感謝各位的閱讀,以上就是“SpringBoot中定時任務@Scheduled的多線程如何使用”的內容了,經過本文的學習后,相信大家對SpringBoot中定時任務@Scheduled的多線程如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

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

    AI

    北安市| 郴州市| 桐乡市| 金阳县| 龙川县| 禄丰县| 周至县| 岳阳市| 榆社县| 贵德县| 德化县| 南通市| 昭通市| 双鸭山市| 马山县| 佛教| 界首市| 和平县| 拉萨市| 梨树县| 云霄县| 龙门县| 林州市| 澄迈县| 大竹县| 福泉市| 谷城县| 田阳县| 呼和浩特市| 伊宁县| 安塞县| 光泽县| 彭阳县| 大邑县| 博兴县| 中阳县| 大厂| 江门市| 嫩江县| 临武县| 青海省|