springMvc同步与异步
一下是个人观点,不喜勿喷,谢谢各位大佬!!!
默认情况下使用spring是同步的,当然也支持异步以提高程序的吞吐量
下面讲解同步
例如1:
下面代码展示,主线程会睡眠1秒钟之后继续执行。阻塞了主线程
@GetMapping("/order1")
public String order1() throws Exception {
logger.info("主线程开启");
Thread.sleep(1000); // 主线程一秒钟时间处理业务逻辑代码
logger.info("主线程返回");
return "success";
}
测试结果:
2019-07-05 14:22:24.499 INFO 25388 --- [nio-8060-exec-4] com.imooc.web.asyn.AsynController : 主线程开启
2019-07-05 14:22:25.499 INFO 25388 --- [nio-8060-exec-4] com.imooc.web.asyn.AsynController : 主线程返回
controller接口返回:success
下面讲解异步
例子2:
在主线程中使用副线程,副线程阻塞不影响主线程的执行
// 使用主线程调用副线程执行业务逻辑代码
@GetMapping("/order2")
public Callable<String> order2()throws Exception{
logger.info("主线程开启");
Callable<String> result = new Callable<String>() {
@Override
public String call() throws Exception {
logger.info("副线程开启");
Thread.sleep(1000); // 副线程一秒钟时间处理业务逻辑代码
logger.info("副线程结束");
return "success";
}
};
logger.info("主线程返回");
return result;
}
测试结果:
2019-07-05 14:23:02.746 INFO 25388 --- [nio-8060-exec-5] com.imooc.web.asyn.AsynController : 主线程开启
2019-07-05 14:23:02.746 INFO 25388 --- [nio-8060-exec-5] com.imooc.web.asyn.AsynController : 主线程返回
2019-07-05 14:23:02.747 INFO 25388 --- [ MvcAsync2] com.imooc.web.asyn.AsynController : 副线程开启
2019-07-05 14:23:03.748 INFO 25388 --- [ MvcAsync2] com.imooc.web.asyn.AsynController : 副线程结束
controller接口返回:success
例子3:
controller
// 使用DeferredResult异步处理Rest服务
@GetMapping("/order3")
public DeferredResult<String> order3(){
logger.info("主线程开启");
String numeric = RandomStringUtils.randomNumeric(8); // 创建订单号
mockQueue.setPlaceOrder(numeric); // 将订单加入队列
DeferredResult<String> result = new DeferredResult<>();
deferredResultHolder.getMap().put(numeric,result);
logger.info("主线程关闭");
return result;
}
MockQueue
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 订单队列
*/
@Component
public class MockQueue {
private String placeOrder; // 订单
private String completeOrder; // 完成了
private Logger logger = LoggerFactory.getLogger(getClass());
public String getPlaceOrder() {
return placeOrder;
}
public void setPlaceOrder(String placeOrder) {
new Thread(() ->{
logger.info("接到下单请求:"+placeOrder);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.completeOrder = placeOrder;
logger.info("下单请求处理完毕:"+placeOrder);
}).start();
}
public String getCompleteOrder() {
return completeOrder;
}
public void setCompleteOrder(String completeOrder) {
this.completeOrder = completeOrder;
}
}
DeferredResultHolder
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.HashMap;
import java.util.Map;
@Component
public class DeferredResultHolder {
private Map<String,DeferredResult<String>> map = new HashMap<>();
public Map<String, DeferredResult<String>> getMap() {
return map;
}
public void setMap(Map<String, DeferredResult<String>> map) {
this.map = map;
}
}
QueueListener。spring监听器
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component // 配置spring监听器加入spring组件
public class QueueListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
new Thread(() ->{
while (true){ // spring监听器中使用while(true)一定要记得不要占用主线程资源,否则会造成线程阻塞
if(StringUtils.isNotBlank(mockQueue.getCompleteOrder())){
String completeOrder = mockQueue.getCompleteOrder();
logger.info("返回订单处理结果:"+completeOrder);
deferredResultHolder.getMap().get(completeOrder).setResult("place order success");
mockQueue.setCompleteOrder(null);
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
测试结果:
2019-07-05 14:24:20.978 INFO 25388 --- [nio-8060-exec-3] com.imooc.web.asyn.AsynController : 主线程开启
2019-07-05 14:24:20.980 INFO 25388 --- [nio-8060-exec-3] com.imooc.web.asyn.AsynController : 主线程关闭
2019-07-05 14:24:20.980 INFO 25388 --- [ Thread-23] com.imooc.web.asyn.MockQueue : 接到下单请求:57259741
2019-07-05 14:24:21.980 INFO 25388 --- [ Thread-23] com.imooc.web.asyn.MockQueue : 下单请求处理完毕:57259741
2019-07-05 14:24:22.237 INFO 25388 --- [ Thread-16] com.imooc.web.asyn.QueueListener : 返回订单处理结果:57259741
controller接口返回:place order success