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

SpringBoot中的異步執(zhí)行方法詳解

 更新時間:2023年10月19日 08:33:41   作者:yfs1024  
這篇文章主要介紹了SpringBoot中的異步執(zhí)行方法詳解,ThreadpoolTaskExecutor不需要手動的創(chuàng)建當前線程池,但往往我們還是會手動指定,具體原因看源碼就可以自有判斷,需要的朋友可以參考下

源碼跟蹤

簡單描述

在SpringBoot2.0.9之前需要手動自定義線程池(如下2.1), 然后指定線程池的名稱

SpringBoot2.0.9以及之前的版本,使用的線程池默認是SimpleAsyncTaskExcutor, 之后的版本使用的是ThreadpoolTaskExecutor

并且不需要手動的創(chuàng)建當前線程池(但往往我們還是會手動指定,具體原因看源碼就可以自有判斷 )

SpringBoot會自動的掃描兩個文件下的配置信息:

所以如果我們寫的配置類想讓SpringBoot自動掃描到就可以放到兩個中的任意一個

我們項目中就是這樣使用的:在 spring.factories文件中指定一些配置類相對路徑,這樣配置類中的指定的Bean就可以放入到IOC容器中了

SpringBoot在org.springframework.boot.autoconfigure.AutoConfiguration.imports118行配置了TaskExecutionAutoConfiguration的位置,這樣SpringBoot就可以掃描到當前配置類

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sOUosu98-1685781636628)(C:\Users\57589\AppData\Roaming\Typora\typora-user-images\image-20230603155549533.png)]

TaskExecutionAutoConfiguration

配置類信息如下

@ConditionalOnClass({ThreadPoolTaskExecutor.class})   // 代表如果容器中有這個類,就不在創(chuàng)建
@AutoConfiguration
@EnableConfigurationProperties({TaskExecutionProperties.class})  // 配置文件
public class TaskExecutionAutoConfiguration {
    // 應用程序任務執(zhí)行器任務名稱 applicationTaskExecutor
    public static final String APPLICATION_TASK_EXECUTOR_BEAN_NAME = "applicationTaskExecutor";

    public TaskExecutionAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean
    public TaskExecutorBuilder taskExecutorBuilder(TaskExecutionProperties properties, ObjectProvider<TaskExecutorCustomizer> taskExecutorCustomizers, ObjectProvider<TaskDecorator> taskDecorator) {
        Pool pool = properties.getPool();
        TaskExecutorBuilder builder = new TaskExecutorBuilder();
        builder = builder.queueCapacity(pool.getQueueCapacity());
        builder = builder.corePoolSize(pool.getCoreSize());
        builder = builder.maxPoolSize(pool.getMaxSize());
        builder = builder.allowCoreThreadTimeOut(pool.isAllowCoreThreadTimeout());
        builder = builder.keepAlive(pool.getKeepAlive());
        Shutdown shutdown = properties.getShutdown();
        builder = builder.awaitTermination(shutdown.isAwaitTermination());
        builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
        builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
        Stream var10001 = taskExecutorCustomizers.orderedStream();
        var10001.getClass();
        builder = builder.customizers(var10001::iterator);
        builder = builder.taskDecorator((TaskDecorator)taskDecorator.getIfUnique());
        return builder;
    }

    @Lazy
    @Bean(
        name = {"applicationTaskExecutor", "taskExecutor"}
    )
    @ConditionalOnMissingBean({Executor.class})
    public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
        return builder.build();
    }

TaskExecutionProperties

配置文件中

定義了線程名 task -

ThreadPoolTaskExecutor

public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
		implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {

	private final Object poolSizeMonitor = new Object();

	private int corePoolSize = 1;

	private int maxPoolSize = Integer.MAX_VALUE;

	private int keepAliveSeconds = 60;

	private int queueCapacity = Integer.MAX_VALUE;

	private boolean allowCoreThreadTimeOut = false;

	private boolean prestartAllCoreThreads = false;
	
	//       ......  ......................省略
	// 創(chuàng)建代碼
	@Override
	protected ExecutorService initializeExecutor(
			ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {

		BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);

		ThreadPoolExecutor executor;
		if (this.taskDecorator != null) {
            // 還是 new ThreadPoolExecutor
			executor = new ThreadPoolExecutor(
					this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
					queue, threadFactory, rejectedExecutionHandler) {
				@Override
				public void execute(Runnable command) {
					Runnable decorated = taskDecorator.decorate(command);
					if (decorated != command) {
						decoratedTaskMap.put(decorated, command);
					}
					super.execute(decorated);
				}
			};
		}
		else {
			executor = new ThreadPoolExecutor(
					this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
					queue, threadFactory, rejectedExecutionHandler);
		}

		if (this.allowCoreThreadTimeOut) {
			executor.allowCoreThreadTimeOut(true);
		}
		if (this.prestartAllCoreThreads) {
			executor.prestartAllCoreThreads();
		}

		this.threadPoolExecutor = executor;
		return executor;
	}

測試代碼:

// 注入
@Autowired
private ThreadPoolTaskExecutor executor;

@Test
public void testThreadPool(){
    System.out.println(executor);
    System.out.println("默認前綴:"+executor.getThreadNamePrefix());
    System.out.println("默認核心線程數(shù):"+executor.getCorePoolSize());
    System.out.println("默認最大線程數(shù):"+executor.getMaxPoolSize());
    System.out.println("當前活躍線程數(shù):"+executor.getActiveCount());
    System.out.println("臨時線程空閑時間:"+executor.getKeepAliveSeconds());
    System.out.println("隊列最大值:"+executor.getQueueCapacity());
    System.out.println("隊列數(shù)量:"+executor.getQueueSize());
}

結(jié)果如下:

org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor@7410c197
默認前綴:task-
默認核心線程數(shù):8
默認最大線程數(shù):2147483647
當前活躍線程數(shù):0
臨時線程空閑時間:60
隊列最大值:2147483647
隊列數(shù)量:0

我們可以看到SpringBoot中默認配置的線程池的數(shù)量, 很不符合我們的實際要求, 而且還容易發(fā)生OOM(Out Of Memory)

所以我們一般是手動指定線程池中的信息

SpringBoot異步執(zhí)行方法

定義一個配置類

SpringBoot底層對手動注入的Bean采用的名稱如果不在@Bean注解后面指定默認采用的是方法名

即: 這里的 generateExchangeCodeExecutor

@Slf4j
@Configuration
public class PromotionConfig {

    @Bean
    public Executor generateExchangeCodeExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 1.核心線程池大小
        executor.setCorePoolSize(2);
        // 2.最大線程池大小
        executor.setMaxPoolSize(5);
        // 3.隊列大小
        executor.setQueueCapacity(200);
        // 4.線程名稱
        executor.setThreadNamePrefix("exchange-code-handler-");
        // 5.拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

在啟動類上添加注解

@EnableAsync

在想要異步執(zhí)行的方法上添加 @Async()注解

并指定ThreadPoolTaskExecutor 執(zhí)行器的名稱

    @Override
    @Async("generateExchangeCodeExecutor")
    public void asyncGenerateCode(Coupon coupon) {
    		......
    }

到此這篇關(guān)于SpringBoot中的異步執(zhí)行方法詳解的文章就介紹到這了,更多相關(guān)SpringBoot異步執(zhí)行內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論