前言:
spring框架中的ThreadPoolTaskExecutor只是对jdk线程池ThreadPoolExecutor的包装
第一种使用方法:
1、springboot启动类中添加线程池配置
/**
* 定义线程池
* @return
*/
@Bean("testThreadPool")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);//配置核心线程数
executor.setMaxPoolSize(20);//配置最大线程数
executor.setKeepAliveSeconds(5);
executor.setQueueCapacity(200);//配置队列大小
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//拒绝策略
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();//执行初始化
return executor;
}
2、注入ThreadPoolTaskExecutor对象
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
3、其他方法和jdk的线程池使用方式相同。
具体参考:https://blog.csdn.net/sumengnan/article/details/105156397中的demo
第二种使用方法:
1、springboot启动类中添加线程池配置和@EnableAsync注解
/**
* 定义线程池
* @return
*/
@Bean("testThreadPool")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);//配置核心线程数
executor.setMaxPoolSize(20);//配置最大线程数
executor.setKeepAliveSeconds(5);
executor.setQueueCapacity(200);//配置队列大小
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//拒绝策略
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();//执行初始化
return executor;
}
2、业务方法上使用@Async注解
package com.sumengnan.test.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class TestServiceImpl {
//volatile保证了静态变量的可见性(visibility),
public static volatile AtomicInteger i = new AtomicInteger(0);
/**
* 无返回结果
*/
@Async("testThreadPool")
public void test() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前第"+ i.incrementAndGet() +"次执行");
}
/**
* 有返回结果
* @return
*/
@Async("testThreadPool")
public Future<String> test2() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult("当前第"+ i.incrementAndGet() +"次执行");
}
}
3、直接调用异步方法即可
package com.sumengnan.test.web;
import com.sumengnan.test.service.TestServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@RestController
public class TestController {
@Autowired
private TestServiceImpl testServiceImpl;
/**
* 无返回值
* @param request
*/
@GetMapping("test")
public void test(HttpServletRequest request){
TestServiceImpl.i=new AtomicInteger(0);
//循环230次
for (int i = 0; i <230; i++) {
System.out.println("第"+(i+1)+"个任务加入队列");
testServiceImpl.test();
}
System.out.println("已全部加入队列");
}
/**
* 有返回值
* @param request
*/
@GetMapping("test2")
public void test2(HttpServletRequest request) throws ExecutionException, InterruptedException {
TestServiceImpl.i=new AtomicInteger(0);
//循环230次
for (int i = 0; i <230; i++) {
System.out.println("第"+(i+1)+"个任务加入队列");
Future<String> future = testServiceImpl.test2();
System.out.println(future.get());
}
System.out.println("已全部加入队列");
}
}
看结果:
注意:
关于@Async注解失效需要注意以下几点:
1,注解的方法必须是public方法。
2,方法一定要从另一个类中调用,也就是从类的外部调用,类的内部调用是无效的。因为@Transactional和@Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。那么注解失效的原因就很明显了,有可能因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器。
3,异步方法使用注解@Async的返回值只能为void或者Future。