Springboot使用异步线程池处理异步任务方法总结

Springboot使用异步线程池多线程处理耗时任务方法总结

  • 本文基于springboot,总结了使用异步线程池处理耗时任务的方法

一、不使用自定义的线程池(简单的异步调用)

1.1 最简单的异步调用,不返回值

import java.util.concurrent.TimeUnit

@Component
public class AsyncDemo {
 
	/**
	* 最简单的异步调用,不返回值
	* @Param sleepSecond
	* @Return void
	*/
	@Async
	public void asyncVoidTest(Integer sleepSecond) {
	 
	 	TimeUnit timeUnit = TimeUnit.SECONDS;

		timeUnit.sleep(sleepSecond);
	 	
		System.our.println("This is the async void test");
	 
	}

}

1.2 异步调用返回Future类

  • 在并发编程中,我们经常用到非阻塞的模型,通过实现Callback接口,并用Future可以来接收多线程的执行结果,使用示例如下:
import java.util.concurrent.TimeUnit
import java.util.concurrent.Future;

@Component
public class AsyncDemo {
 
	/**
	* 异步调用返回Future类
	* @param i
	* @return
	*/
	@Async
	public Future<String> asyncFutureTest(int i) {
		 
		Future<String> future;
		 
		try {
		 
			Thread.sleep(1000 * 1);
			 
			future = new AsyncResult<String>("success:" + i);
		 
		} catch (InterruptedException e) {
		 
			future = new AsyncResult<String>("error");
		 
		}
		 
		return future;
 
	}

}

1.3 设置定时任务

  • 我们还可以通过@Scheduled注解来进行异步定时任务的设置,可以通过设置fixedDelay、initialDelay等参数来使用,也可以通过cron表达式来进行使用
  • cron表达式的使用方法可以参考我的博文Cron表达式详细解析
  • 使用示例如下:
import java.util.concurrent.TimeUnit

@Component
public class AsyncDemo {
 
	/**
	* 不使用cron表达式的定时器设置方法
	* initialDelay表示容器启动初始化后延迟5秒后执行一次定时器,fixedDelay表示每10秒执行一次定时器
	* 如果想一开始就直接执行定时器的话,不设置initialDelay即可
	* fixedDelay和initialDelay的单位都是1000表示1秒
	* @Param sleepSecond
	* @Return void
	*/
	@Async
	@Scheduled(fixedDelay=1000 * 10, initialDelay=1000 * 5)
	public void asyncNoCronTimerTest(Integer sleepSecond) {
	 
	 	TimeUnit timeUnit = TimeUnit.SECONDS;

		timeUnit.sleep(sleepSecond);
	 	
		System.our.println("This is the async no cron timer test");
	 
	}

	/**
	* 使用cron表达式的定时器设置方法
	* @Param sleepSecond
	* @Return void
	*/
	@Async
	@Scheduled(cron = "* * * * * ?")
	public void asyncCronTimerTest(Integer sleepSecond) {
	 
	 	TimeUnit timeUnit = TimeUnit.SECONDS;

		timeUnit.sleep(sleepSecond);
	 	
		System.our.println("This is the async cron timer test");
	 
	}

}

二、使用自定义的线程池(推荐使用此方法)

2.1 添加自定义线程池配置类

因为Springboot框架默认来一个请求开启一个线程,在高并发下容易内存溢出
所以使用时最好通过配置自定义线程池来进行处理异步任务

  • 新建一个配置类,例如建一个ThreadPoolConfig.java,代码如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ThreadPoolConfig {

	// @Bean里边的name可自定义成想要的内容
    @Bean("MyThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        //  线程池创建的核心线程数,线程池维护现线程的最小数量,即使没有任务需要执行,也会一直存活
        executor.setCorePoolSize(16);

        //  如果设置allowCoreThreadTimeOut=true(默认false)时,核心线程会超时关闭
        //  executor.setAllowCoreThreadTimeout(true)
        //  阻塞队列,当核心线程达到最大时,新任务会放在队列中排队等待执行
        executor.setQueueCapacity(124);

        //  最大线程池数量,当线程数>=corePoolSize,且任务队列已满时,线程池会创建新线程来处理任务
        //  任务队列已满时,且当线程数=maxPoolSize,线程池会拒绝处理任务而抛出异常
        executor.setMaxPoolSize(64);

        //  当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数=corePoolSize
        //  允许线程空闲时间30秒,当maxPoolSize的线程在空闲时间到达的时候销毁
        //  如果allowCoreThreadTimeOut=true,则会直到线程数量=0
        executor.setKeepAliveSeconds(30);

        //  spring 提供的 ThreadPoolTaskExecutor 线程池是有setThreadNamePrefix()方法的
        //  jdk 提供的 ThreadPoolTaskExecutor 线程池是没有setThreadNamePrefix()方法的
        executor.setThreadNamePrefix("目标特性提取系统线程池");

        //  rejection-policy:拒绝策略, 当线程数已经达到maxSize时候,如何处理新任务
        //  CallerRunsPolicy():交由调用方线程运行,比如main线程,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行
        //  AbortPolicy():该策略时线程池的默认策略,如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException
        //  DiscardPolicy():如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常
        //  DiscardOldestPolicy():丢弃队列中最老的任务,队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        executor.initialize();

        return executor;

    }

}

2.2 使用自定义线程池

  • 配置类添加好后,在使用@Async时直接把ThreadPoolConfig里边的Bean的name直接添加即可正常使用我们自定义的线程池了,使用示例如下:
~~~java
import java.util.concurrent.TimeUnit

@Component
public class AsyncDemo {
 
	/**
	* 使用自定义线程池
	* @Param sleepSecond
	* @Return void
	*/
	@Async("MyThreadPoolTaskExecutor")
	public void asyncMyThreadPoolTest(Integer sleepSecond) {
	 
	 	TimeUnit timeUnit = TimeUnit.SECONDS;

		timeUnit.sleep(sleepSecond);
	 	
		System.our.println("This is the async my thread pool test");
	 
	}

}

以上就是Springboot使用异步线程池处理异步任务的方法,我感觉还是相对比较简单的,谢谢愿意收看我的博文的朋友,下期见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nikolas06

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值