ThreadPoolTaskExecutor是一个spring的线程池技术,被叫成什么异步线程执行器。
本质上是使用的java.util.concurrent.ThreadPoolExecutor
一、配置类`
@Configuration
public class TaskConfig {
@Bean("taskModuleExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("task-concurrent-work");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}}
`
参数说明:
int corePoolSize:线程池维护线程的最小数量.
int maxPoolSize:线程池维护线程的最大数量.
int maxPoolSize:线程池维护线程的最大数量.
long keepAliveTime:空闲线程的存活时间.
TimeUnit unit: 时间单位,现有纳秒,微秒,毫秒,秒枚举值.
BlockingQueue<Runnable> workQueue:持有等待执行的任务队列.
RejectedExecutionHandler handler: 用来拒绝一个任务的执行,有两种情况会发生这种情况。
处理流程:
当池子大小小于corePoolSize,就新建线程,并处理请求
当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
二、定义线程类`
@Component
public class FileCutter {
@Resource(name="taskModuleExecutor")
private TaskExecutor taskExecutor;
public void filesMng(String path, String fileName) {
this.taskExecutor.execute(new CutFilesThread(path,fileName));
}
private class CutFilesThread implements Runnable {
private String path;
private String fileName;
private CutFilesThread(String path, String fileName) {
super();
this.path = path;
this.fileName = fileName;
}
@Override
public void run() {
System.out.println("barry... run...");
//display(path, fileName);
}
}
`
如果想要得到任务返回结果,可以将execute方法改为调用submit方法即可。
`
String resp="";
Future<String> task = threadPool.submit(new Callable<String>(){
@Override
public String call() throws Exception {
String callbackResp = HttpUtils.post(Url, params, "utf-8");
return callbackResp;
}
});
try { //注意task.get()会阻塞,直到返回数据为止,一般这样用法很少用
resp=task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}`
三、在需要的地方调用
`
@Autowired
private FileCutter fileCutter;
@RequestMapping("/cut")
@ResponseBody
public Object cut(){
fileCutter.filesMng("your path", "your fileName");
return "success";
}
`
四、使用springboot@Async注解
springboot中为我们提供了@Async注解,查看下源码`
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
String value() default "";
}
`
我们发现,@Async是一个类级别和方法级别的注解,当作用在方法上时,相当于这个方法重新开辟了单独的线程。
使用案例:
Controller层`
@RestController
public class controller {
@Autowired
private AsyncService asyncService;
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String test2(){
long start=System.currentTimeMillis();
asyncService.NoReturn();
return String.format("任务执行成功,耗时{%s}",System.currentTimeMillis() - start);
}
}`
接下来在service层添加@Async`
@Service
public class AsyncService {
@Async
public void NoReturn(){
try{
Thread.sleep(3000);
System.out.println("方法执行结束"+new Date());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}`
在启动类开启异步请求`
@EnableAsync//开启异步任务
@SpringBootApplication
public class Springboot5Application {
public static void main(String[] args) {
SpringApplication.run(Springboot5Application.class, args);
}
}`
有返回值的异步
service层`
@Service
public class AsyncService {
@Async
public Future<String> doReturn(int i){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(String.format("这个是第{%s}个异步调用的证书",i));
}
}
`
controller层`
@RestController
public class controller {
@GetMapping("/hi")
public Map<String,Object> testAsyncReturn()throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
Map<String,Object> map=new HashMap<>();
List<Future<String>> futures=new ArrayList<>();
for (int i=0;i<10;i++){
Future<String> future =asyncService.doReturn(i);
futures.add(future);
}
List<String> response =new ArrayList<>();
for (Future future : futures){
String string =(String) future.get();
response.add(string);
}
map.put("data",response);
map.put("消耗时间",String.format("任务完成,耗时{%s}毫秒",System.currentTimeMillis()-start));
return map;
}
}
`
查看结果:
{“data”:[“这个是第{0}个异步调用的证书”,“这个是第{1}个异步
调用的证书”,“这个是第{2}个异步调用的证书”,“这个是第{3}个异步调用的证书”,“这个是第{4}个异步调用的证书”,“这个是第{5}个异步调用的证书”,“这个是第{6}个异步调用的证书”,“这个是第{7}个异步调用的证书”,“这个是第{8}个异步调用的证书”,“这个是第{9}个异步调用的证书”],“消耗时间”:“任务完成,耗时{1004}毫秒”}
注意:注解扫描时,要注意过滤,避免重复实例化,因为存在覆盖问题,@Async就失效了