SpingBoot @Async的使用
项目工程结构
定义一个业务类,有4个业务
package com.demo.testasync.service;
import java.util.concurrent.Future;
public interface TestService {
/**
* 异步调用,无返回值
*/
void asyncTask1();
/**
* 异步调用,无返回值
*/
void asyncTask2();
/**
* 异步调用,有返回值
*
* @param s 年代
* @return {@link Future}
* Future表示一个可能还没有完成的异步任务的结果
*/
Future asyncTask1(String s);
/**
* 异步调用,有返回值
*
* @param s 年代
* @return {@link Future}
* Future表示一个可能还没有完成的异步任务的结果
*/
Future asyncTask2(String s);
}
业务实现类
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.Future;
@Service
public class TestServiceImpl implements TestService {
@Async("doAsyncTaskExecutor")
@Override
public void asyncTask1() {
long startTime = System.currentTimeMillis();
// 模拟耗时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread() + ",asyncTask(),耗时:" + (endTime - startTime));
}
@Async("doAsyncTaskExecutor")
@Override
public void asyncTask2() {
long startTime = System.currentTimeMillis();
// 模拟耗时
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread() + ",asyncTask(),耗时:" + (endTime - startTime));
}
@Async("doAsyncTaskExecutor")
@Override
public Future asyncTask1(String s) {
long startTime = System.currentTimeMillis();
// 模拟耗时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread() + ",asyncTask(String s),耗时:" + (endTime - startTime));
return AsyncResult.forValue(s);
}
@Async("doAsyncTaskExecutor")
@Override
public Future asyncTask2(String s) {
long startTime = System.currentTimeMillis();
// 模拟耗时
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread() + ",asyncTask(String s),耗时:" + (endTime - startTime));
return AsyncResult.forValue(s);
}
}
线程池配置
配置完成后@Async
会默认从线程池获取线程,当然也可以显式的指定@Async("doAsyncTaskExecutor")
package com.demo.testasync.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class AsyncConfig {
private static final int MAX_POOL_SIZE = 500;
private static final int CORE_POOL_SIZE = 20;
@Bean("doAsyncTaskExecutor")
AsyncTaskExecutor doAsyncTaskExecutor(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
//配置核心线程数
threadPoolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
//配置最大线程数
threadPoolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
//配置队列大小
threadPoolTaskExecutor.setQueueCapacity(200);
//线程池维护线程所允许的空闲时间
threadPoolTaskExecutor.setKeepAliveSeconds(30);
//配置线程池中的线程的名称前缀
threadPoolTaskExecutor.setThreadNamePrefix("yoyo");
//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
//设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
threadPoolTaskExecutor.setAwaitTerminationSeconds(60);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
在ApplicationRunner中初始化业务方法的实现,这样启动项目后,业务方法会自动异步执行
package com.demo.testasync.job;
import com.demo.testasync.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class RunThread {
@Autowired
TestService testService;
@Bean
public ApplicationRunner applicationRunner() {
return applicationArguments -> {
long startTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + ":开始调用异步业务");
//无返回值
testService.asyncTask1();
testService.asyncTask2();
testService.asyncTask1("haha1");
testService.asyncTask2("haha2");
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + ":调用异步业务结束,耗时:" + (endTime - startTime));
};
}
}
在启动类上加上@EnableAsync
注解
package com.demo.testasync;
import com.demo.testasync.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
@SpringBootApplication
@EnableAsync
public class TestasyncApplication {
public static void main(String[] args) {
SpringApplication.run(TestasyncApplication.class, args);
}
}