欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中定時任務(wù)@Scheduled的多線程使用詳解

 更新時間:2023年04月21日 16:38:49   作者:Cosolar  
這篇文章主要為大家詳細(xì)介紹了pring Boot定時任務(wù)@Scheduled的多線程原理以及如何加入線程池來處理定時任務(wù),感興趣的可以了解一下

一、@Scheduled注解簡介

@Scheduled是Spring框架中的一個注解,它可以用于配置定時任務(wù),使得方法可以按照規(guī)定的時間間隔定時執(zhí)行。在使用該注解時,我們可以指定任務(wù)的執(zhí)行時間、循環(huán)周期、并發(fā)數(shù)等參數(shù),從而實現(xiàn)定時任務(wù)的功能。在Spring Boot中,@Scheduled注解可以直接應(yīng)用于方法上。

二、@Scheduled的多線程機(jī)制

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

三、@Scheduled的多線程問題

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

1.定時任務(wù)未執(zhí)行完畢時,后續(xù)任務(wù)可能會受到影響

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

2.多個定時任務(wù)并發(fā)執(zhí)行可能導(dǎo)致資源競爭

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

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

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

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來創(chuàng)建一個線程池,并使用@EnableScheduling注解將定時任務(wù)開啟。其中,setPoolSize方法可以設(shè)置線程池的大小,默認(rèn)為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來創(chuàng)建一個線程池,并使用@EnableScheduling注解將定時任務(wù)開啟。其中setCorePoolSize、setMaxPoolSize、setQueueCapacity、setKeepAliveSeconds等方法可以用于配置線程池的大小和任務(wù)隊列等參數(shù)。

五、@Scheduled詳細(xì)分析

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

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

1. 定時任務(wù)未執(zhí)行完畢時,后續(xù)任務(wù)可能會受到影響

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

解決方案:

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

方案一:修改線程池大小

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

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

spring.task.scheduling.pool.size=20

2. 多個定時任務(wù)并發(fā)執(zhí)行可能導(dǎo)致資源競爭

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

解決方案:

為了避免由于多個定時任務(wù)并發(fā)執(zhí)行導(dǎo)致的資源競爭問題,我們可以采用以下兩種方案來解決:

方案一:使用鎖機(jī)制

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

例如,下面是一個使用synchronized關(guān)鍵字實現(xiàn)鎖機(jī)制的示例:

private static Object lockObj = new Object();

@Scheduled(fixedDelay = 1000)
public void doSomething(){
    synchronized(lockObj){
        // 定時任務(wù)要執(zhí)行的內(nèi)容
    }
}

在上述代碼中,我們定義了一個靜態(tài)對象lockObj,用來保護(hù)共享資源。在定時任務(wù)執(zhí)行時,我們使用synchronized關(guān)鍵字對lockObj進(jìn)行加鎖,從而確保多個定時任務(wù)不能同時訪問共享資源。

方案二:使用分布式鎖

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

在Java開發(fā)中,我們可以使用ZooKeeper、Redis等分布式系統(tǒng)來實現(xiàn)分布式鎖機(jī)制。例如,使用Redis實現(xiàn)分布式鎖的示例代碼如下:

@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{
            // 定時任務(wù)要執(zhí)行的內(nèi)容
        }finally{
            redisTemplate.delete(lockKey);
        }
    }
}

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

六、總結(jié)

通過以上的分析,我們可以了解到:雖然@Scheduled注解能夠非常方便地實現(xiàn)定時任務(wù)的功能,但是它也存在一些多線程的問題。為此,需要注意到這些問題,并采取相應(yīng)的措施來避免它們的出現(xiàn)。在實際開發(fā)中,可以結(jié)合使用線程池、異步線程池、鎖機(jī)制、分布式鎖等方式,達(dá)到最佳的效果。

到此這篇關(guān)于SpringBoot中定時任務(wù)@Scheduled的多線程使用詳解的文章就介紹到這了,更多相關(guān)SpringBoot定時任務(wù)@Scheduled內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Java如何實現(xiàn)有效的并發(fā)處理

    詳解Java如何實現(xiàn)有效的并發(fā)處理

    隨著互聯(lián)網(wǎng)的蓬勃發(fā)展,現(xiàn)代軟件系統(tǒng)對于并發(fā)性能的要求越來越高,如何學(xué)習(xí)和掌握并發(fā)編程技術(shù)成為了Java開發(fā)人員必備的技能之一,本文主要介紹了Java并發(fā)編程的相關(guān)概念、原理和實踐技巧,感興趣的可以了解下
    2023-11-11
  • spring boot 3.3.0和mybatis plus 3.5.6版本沖突的問題解決

    spring boot 3.3.0和mybatis plus 3.5.6版本沖突

    這篇文章主要介紹了spring boot 3.3.0和mybatis plus 3.5.6版本沖突的問題解決,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • SpringBoot中的文件上傳和異常處理詳解

    SpringBoot中的文件上傳和異常處理詳解

    這篇文章主要介紹了SpringBoot中的文件上傳和異常處理詳解,對于機(jī)器客戶端,它將生成JSON響應(yīng),其中包含錯誤,HTTP狀態(tài)和異常消息的詳細(xì)信息,對于瀏覽器客戶端,響應(yīng)一個"whitelabel"錯誤視圖,以HTML格式呈現(xiàn)相同的數(shù)據(jù),需要的朋友可以參考下
    2023-09-09
  • Java設(shè)計模式之Strategy模式

    Java設(shè)計模式之Strategy模式

    Strategy模式即策略模式,就是將一個算法的不同實現(xiàn)封裝成一個個單獨的類,這些類實現(xiàn)同一個接口,使用者直接使用該接口來訪問具體的算法。這個樣子,使用者就可以使用不同的算法來實現(xiàn)業(yè)務(wù)邏輯了。
    2016-07-07
  • springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例

    springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例

    今天小編就為大家分享一篇關(guān)于springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • java 虛擬機(jī)深入了解

    java 虛擬機(jī)深入了解

    這篇文章主要介紹了java 虛擬機(jī)深入了解的相關(guān)資料,ava虛擬機(jī)有自己完善的硬體架構(gòu),如處理器、堆棧、寄存器等,還具有相應(yīng)的指令系統(tǒng),需要的朋友可以參考下
    2017-03-03
  • java 線程創(chuàng)建多線程詳解

    java 線程創(chuàng)建多線程詳解

    本文主要講解java 線程創(chuàng)建多線程的知識,這里對java線程的創(chuàng)建做了詳細(xì)介紹,并附簡單示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • MyBatis傳入?yún)?shù)的實例代碼

    MyBatis傳入?yún)?shù)的實例代碼

    這篇文章主要介紹了MyBatis傳入?yún)?shù)的實例代碼的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • 解決nacos的yml配置文件解析@開頭的值啟動報錯問題

    解決nacos的yml配置文件解析@開頭的值啟動報錯問題

    這篇文章主要介紹了解決nacos的yml配置文件解析@開頭的值啟動報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 詳解java調(diào)用存儲過程并封裝成map

    詳解java調(diào)用存儲過程并封裝成map

    這篇文章主要介紹了詳解java調(diào)用存儲過程并封裝成map的相關(guān)資料,希望通過本文能幫助到大家實現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-09-09

最新評論