最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring定時(shí)任務(wù)并行(異步)處理方式

 更新時(shí)間:2024年08月02日 15:36:28   作者:BlueKitty1210  
這篇文章主要介紹了Spring定時(shí)任務(wù)并行(異步)處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring定時(shí)任務(wù)并行(異步)

最近項(xiàng)目中遇到一個(gè)問題 , 在SpringBoot中設(shè)置了定時(shí)任務(wù)之后 , 在某個(gè)點(diǎn)總是沒有執(zhí)行 . 經(jīng)過搜索研究發(fā)現(xiàn) , spring 定時(shí)器任務(wù)scheduled-tasks默認(rèn)配置是單線程串行執(zhí)行的 .

即在當(dāng)前時(shí)間點(diǎn)之內(nèi) . 如果同時(shí)有兩個(gè)定時(shí)任務(wù)需要執(zhí)行的時(shí)候 , 排在第二個(gè)的任務(wù)就必須等待第一個(gè)任務(wù)執(zhí)行完畢執(zhí)行才能正常運(yùn)行.

如果第一個(gè)任務(wù)耗時(shí)較久的話 , 就會(huì)造成第二個(gè)任務(wù)不能及時(shí)執(zhí)行 .

這樣就可能由于時(shí)效性造成其他問題 . 而在實(shí)際項(xiàng)目中 , 我們也往往需要這些定時(shí)任務(wù)是"各干各的" , 而不是排隊(duì)執(zhí)行.

以下為默認(rèn)串行的定時(shí)任務(wù)代碼

package com.xbz.timerTask.task;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @title 測(cè)試spring定時(shí)任務(wù)執(zhí)行
 * @createDate 2017年8月18日
 * @version 1.0
 */
@Component
@Configuration
@EnableScheduling
public class MyTestTask {
    private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Scheduled(fixedDelay = 1000)
    public void executeUpdateYqTask() {
        System.out.println(Thread.currentThread().getName() + " >>> task one " + format.format(new Date()));
    }

    @Scheduled(fixedDelay = 1000)
    public void executeRepaymentTask() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " >>> task two " + format.format(new Date()));
        Thread.sleep(5000);
    }
}

啟動(dòng)項(xiàng)目之后 , 發(fā)現(xiàn)控制臺(tái)輸出如下 :

可以發(fā)現(xiàn) , 一直是pool-5-thread-1一個(gè)線程在執(zhí)行定時(shí)任務(wù) , 這顯然不符合我們的業(yè)務(wù)需求.

如何把定時(shí)任務(wù)改造成異步呢 , 在spring中網(wǎng)上文檔較多 , 不再敘述 . 但在SpringBoot找到的相關(guān)資料也是新建xml文件的方式配置 , 實(shí)際上這就違背了SpringBoot減少配置文件的初衷 .

在SpringBoot可以自定義以下線程池配置

package com.xbz.config;

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer{

	/** 異步處理 */
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar){
		TaskScheduler taskScheduler = taskScheduler();
		taskRegistrar.setTaskScheduler(taskScheduler);
	}

	/** 定時(shí)任務(wù)多線程處理 */
	@Bean(destroyMethod = "shutdown")
	public ThreadPoolTaskScheduler taskScheduler(){
		ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
		scheduler.setPoolSize(20);
		scheduler.setThreadNamePrefix("task-");
		scheduler.setAwaitTerminationSeconds(60);
		scheduler.setWaitForTasksToCompleteOnShutdown(true);
		return scheduler;
	}

	/** 異步處理 */
	public Executor getAsyncExecutor(){
		Executor executor = taskScheduler();
		return executor;
	}

	/** 異步處理 異常 */
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){
		return new SimpleAsyncUncaughtExceptionHandler();
	}
}

此時(shí)再啟動(dòng)定時(shí)任務(wù) , 就發(fā)現(xiàn)已經(jīng)是異步處理的了 .

如果項(xiàng)目中同時(shí)配置了異步任務(wù)的線程池和定時(shí)任務(wù)的異步線程處理

配置類如下 :

package com.xbz.config;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
 * @title 使用自定義的線程池執(zhí)行異步任務(wù) , 并設(shè)置定時(shí)任務(wù)的異步處理 
 * @version 1.0
 */
@Configuration
@EnableAsync
@EnableScheduling
public class ExecutorConfig implements SchedulingConfigurer, AsyncConfigurer {

    private static final Logger LOG = LogManager.getLogger(ExecutorConfig.class.getName());

    @Autowired
    private TaskThreadPoolConfig config;

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(config.getCorePoolSize());
        executor.setMaxPoolSize(config.getMaxPoolSize());
        executor.setQueueCapacity(config.getQueueCapacity());
        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
        executor.setThreadNamePrefix("taskExecutor-");

        // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是由調(diào)用者所在的線程來執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    /**
     * @title 異步任務(wù)中異常處理 
     * @description 
     * @author Xingbz
     * @createDate 2017年9月11日
     * @return
     * @see org.springframework.scheduling.annotation.AsyncConfigurer#getAsyncUncaughtExceptionHandler()
     * @version 1.0
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandler() {
            @Override
            public void handleUncaughtException(Throwable ex, Method method, Object... params) {
                LOG.error("==========================" + ex.getMessage() + "=======================", ex);
                LOG.error("exception method:" + method.getName());
            }
        };
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        TaskScheduler taskScheduler = taskScheduler();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }
    
    /**
     * 并行任務(wù)使用策略:多線程處理
     * 
     * @return ThreadPoolTaskScheduler 線程池
     */
     @Bean(destroyMethod = "shutdown")
     public ThreadPoolTaskScheduler taskScheduler() {
         ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
         scheduler.setPoolSize(config.getCorePoolSize());
         scheduler.setThreadNamePrefix("task-");
         scheduler.setAwaitTerminationSeconds(60);
         scheduler.setWaitForTasksToCompleteOnShutdown(true);
         return scheduler;
     }
}

需要注意:

  • 這兩個(gè)配置類只能同時(shí)配置一個(gè) 
  • 如果配置了第二個(gè) , 則第一個(gè)就無需再用

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 圖解程序員必須掌握的Java常用8大排序算法

    圖解程序員必須掌握的Java常用8大排序算法

    本文以圖片與文字結(jié)合的方式講解了程序員必須掌握的Java常用8大排序算法:插入排序、冒泡排序、選擇排序、希爾排序 、快速排序、歸并排序、堆排序和LST基數(shù)排序,需要的朋友可以參考下
    2015-07-07
  • 關(guān)于jdk環(huán)境變量配置以及javac不是內(nèi)部或外部命令的解決

    關(guān)于jdk環(huán)境變量配置以及javac不是內(nèi)部或外部命令的解決

    這篇文章主要介紹了關(guān)于jdk環(huán)境變量配置以及javac不是內(nèi)部或外部命令的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Springboot日期轉(zhuǎn)換器實(shí)現(xiàn)代碼及示例

    Springboot日期轉(zhuǎn)換器實(shí)現(xiàn)代碼及示例

    這篇文章主要介紹了Springboot日期轉(zhuǎn)換器實(shí)現(xiàn)代碼及示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 單例模式 分析代碼優(yōu)化方法

    單例模式 分析代碼優(yōu)化方法

    這篇文章主要介紹了單例模式 分析代碼優(yōu)化方法,需要的朋友可以參考下
    2015-04-04
  • 一文帶你搞懂Java中的遞歸

    一文帶你搞懂Java中的遞歸

    這篇文章主要為大家詳細(xì)介紹了Java中的遞歸的實(shí)現(xiàn)以及應(yīng)用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下
    2022-10-10
  • SpringBoot如何接收Post請(qǐng)求Body里面的參數(shù)

    SpringBoot如何接收Post請(qǐng)求Body里面的參數(shù)

    這篇文章主要介紹了SpringBoot如何接收Post請(qǐng)求Body里面的參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解如何使用MongoDB+Springboot實(shí)現(xiàn)分布式ID的方法

    詳解如何使用MongoDB+Springboot實(shí)現(xiàn)分布式ID的方法

    這篇文章主要介紹了詳解如何使用MongoDB+Springboot實(shí)現(xiàn)分布式ID的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • jdk1.8的環(huán)境配置過程

    jdk1.8的環(huán)境配置過程

    Java平臺(tái)由Java虛擬機(jī)和Java應(yīng)用程序接口搭建,Java語言則是進(jìn)入這個(gè)平臺(tái)的通道,用Java語言編寫并編譯的程序可以運(yùn)行在這個(gè)平臺(tái)上,本文給大家講解jdk1.8的環(huán)境配置過程,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • Mybatis攔截器的實(shí)現(xiàn)介紹

    Mybatis攔截器的實(shí)現(xiàn)介紹

    MyBatis提供了一種插件(plugin)的功能,雖然叫做插件,但其實(shí)這是攔截器功能。MyBatis 允許你在已映射語句執(zhí)行過程中的某一點(diǎn)進(jìn)行攔截調(diào)用。下面通過本文給大家介紹Mybatis攔截器知識(shí),感興趣的朋友一起看看吧
    2016-10-10
  • Java關(guān)鍵字static的6個(gè)常見誤區(qū)及解決方法

    Java關(guān)鍵字static的6個(gè)常見誤區(qū)及解決方法

    文章主要講述了Java中static關(guān)鍵字的常見誤解和誤區(qū),包括static屬于類而非對(duì)象、靜態(tài)方法不能被重寫、靜態(tài)方法中不能使用this或super、靜態(tài)代碼塊只會(huì)執(zhí)行一次、static變量并非天生線程安全以及要在聲明或靜態(tài)塊中初始化靜態(tài)變量等內(nèi)容,需要的朋友可以參考下
    2026-05-05

最新評(píng)論

钟祥市| 古丈县| 涪陵区| 遂宁市| 西和县| 仪征市| 石城县| 成都市| 嘉禾县| 长沙县| 广水市| 奉贤区| 濮阳市| 嘉荫县| 抚顺县| 山丹县| 上林县| 襄城县| 邢台市| 平阴县| 汪清县| 漯河市| 湘西| 八宿县| 松潘县| 芜湖县| 江华| 新泰市| 昌江| 黎川县| 乐东| 东阳市| 班玛县| 怀仁县| 大洼县| 荣昌县| 台北市| 凤城市| 兴海县| 龙里县| 延安市|