SpringBoot2.1.2 中默认有两出会开启线程池
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
创建Beanorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
创建Beanorg.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
这两个Bean都实现了org.springframework.core.task.AsyncListenableTaskExecutor
和org.springframework.scheduling.SchedulingTaskExecutor
, 所以程序中不能通过这两个类型及其父类类型注入bean.
相关issue: Order TaskExecutionAutoConfiguration before TaskSchedulerAutoConfiguration
package com.bruce.webmvc.controller;
import com.bruce.webmvc.service.AsyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
/**
* SpringMVC 中对Servlet3.0异步请求支持
* 在Spring中使用异步请求时应当提前配置好异步执行线程池
*/
@Slf4j
@RestController
@RequestMapping("/async")
public class SpringAsyncController {
//@Autowired
//private TaskExecutor executor;
@Autowired
private ThreadPoolTaskExecutor executor;
@Autowired
private AsyncService asyncService;
@GetMapping("/callable")
public Callable<String> callable() {
log.info("执行线程" + Thread.currentThread().getName());
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
log.info("执行线程" + Thread.currentThread().getName());
//TimeUnit.SECONDS.sleep(2);
return "任务执行线程是:" + Thread.currentThread().getName();
}
};
log.info("执行线程" + Thread.currentThread().getName());
return callable;
}
//仅java8之后支持
@GetMapping("/completionStage")
public CompletionStage<String> completionStage() {
log.info("执行线程" + Thread.currentThread().getName());
return CompletableFuture.supplyAsync(() -> {
log.info("使用Java8中的CompletableFuture: " + Thread.currentThread().getName());
return Thread.currentThread().getName();
});
}
@GetMapping("/deferredResult")
public DeferredResult<String> deferredResult() {
log.info("执行线程" + Thread.currentThread().getName());
DeferredResult<String> deferredResult = new DeferredResult<>();
executor.execute(new Runnable() {
@Override
public void run() {
log.info("执行线程" + Thread.currentThread().getName());
try {
//TimeUnit.SECONDS.sleep(2);
deferredResult.setResult("任务执行线程是:" + Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
deferredResult.setErrorResult(e.getMessage());
}
}
});
log.info("执行线程" + Thread.currentThread().getName());
return deferredResult;
}
//原生异步servlet用法
@RequestMapping("/servlet1")
public void req1(HttpServletRequest request, HttpServletResponse resp) {
log.info("开始" + Thread.currentThread().getName());
AsyncContext asyncContext = request.startAsync();
executor.execute(new Runnable() {
@Override
public void run() {
try {
log.info("异步线程: " + Thread.currentThread().getName());
Thread.sleep(2000);
resp.getWriter().print("asyncServlet:" + Thread.currentThread().getName());
asyncContext.complete();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
});
log.info("结束" + Thread.currentThread().getName());
}
//错误用法,这中用法也使用了不同线程,但是请求线程和处理线程都是servlet线程
@RequestMapping("/servlet2")
public void req(HttpServletRequest request, HttpServletResponse resp) {
log.info("开始" + Thread.currentThread().getName());
AsyncContext asyncContext = request.startAsync();
asyncContext.start(new Runnable() {
@Override
public void run() {
try {
log.info("异步线程: " + Thread.currentThread().getName());
Thread.sleep(2000);
resp.getWriter().print("asyncServlet:" + Thread.currentThread().getName());
asyncContext.complete();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
});
log.info("结束" + Thread.currentThread().getName());
}
/**
* 后退异步任务默认和Servlet异步请求使用的是同一个线程池
*/
@GetMapping("/task")
public String task() {
asyncService.hello();
return "任务正在后台执行";
}
}