使用多线程提高Rest服务性能

⒈使用Runnable异步处理Rest服务

 1     /**
 2      *使用Runnable异步处理Rest服务
 3      * @return
 4      */
 5     @GetMapping("/order")
 6     public Callable<String> callableOrder(){
 7         logger.info("主线程开始");
 8         System.out.println(Thread.currentThread().getId());
 9         Callable<String> result = new Callable<String>() {
10             @Override
11             public String call() throws Exception {
12                 logger.info("副线程开始");
13                 Thread.sleep(1000);
14                 System.out.println(Thread.currentThread().getId());
15                 logger.info("副线程返回");
16                 return "seccess";
17             }
18         };
19         logger.info("主线程返回");
20         return result;
21     }

Runnable的这种形式并不能满足所有的应用场景,使用Runnable异步处理的时候,副线程必须是由主线程调起的,在实际开发的过程中,有些场景是非常复杂的。

例如,如下场景:

 我们可以使用DeferredResult来解决上面复杂的场景

⒉使用DeferredResult异步处理Rest服务

  1.模拟队列

 1 package cn.coreqi.security.async;
 2 
 3 import org.slf4j.Logger;
 4 import org.slf4j.LoggerFactory;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * 用于模拟消息队列
 9  */
10 @Component
11 public class MockQueue {
12 
13     private String placeOrder;  //代表下单的消息
14 
15     private String completeOrder;   //代表订单完成的消息
16 
17     private Logger logger = LoggerFactory.getLogger(getClass());
18 
19     public String getPlaceOrder() {
20         return placeOrder;
21     }
22 
23     public void setPlaceOrder(String placeOrder){
24         new Thread(() -> {
25             logger.info("接到下单请求!" + placeOrder);
26             try {
27                 Thread.sleep(1000);
28             } catch (InterruptedException e) {
29                 e.printStackTrace();
30             }
31             this.completeOrder = placeOrder;
32             logger.info("下单请求处理完成!" + placeOrder);
33         }).start();
34     }
35 
36     public String getCompleteOrder() {
37         return completeOrder;
38     }
39 
40     public void setCompleteOrder(String completeOrder) {
41         this.completeOrder = completeOrder;
42     }
43 }

  2.模拟结果

  

 1 package cn.coreqi.security.async;
 2 
 3 import org.springframework.stereotype.Component;
 4 import org.springframework.web.context.request.async.DeferredResult;
 5 
 6 import java.util.HashMap;
 7 import java.util.Map;
 8 
 9 @Component
10 public class DeferredResultHolder {
11 
12     private Map<String, DeferredResult<String>> map = new HashMap<>();  //K为ID,V代表处理结果
13 
14     public Map<String, DeferredResult<String>> getMap() {
15         return map;
16     }
17 
18     public void setMap(Map<String, DeferredResult<String>> map) {
19         this.map = map;
20     }
21 }

  3.控制器处理

 1     @Autowired
 2     private MockQueue mockQueue;
 3 
 4     @Autowired
 5     private DeferredResultHolder deferredResultHolder;
 6 
 7     /**
 8      * 使用DeferredResult异步处理Rest服务
 9      * @return
10      * @throws InterruptedException
11      */
12     @GetMapping("/order")
13     public DeferredResult<String> deferredResultOrder() throws InterruptedException {
14         logger.info("主线程开始");
15         System.out.println(Thread.currentThread().getId());
16         String orderNumber = new Random().longs(8).toString();  //生成订单号
17         mockQueue.setPlaceOrder(orderNumber);   //放入到消息队列里面
18         DeferredResult<String> result = new DeferredResult<>();
19         deferredResultHolder.getMap().put(orderNumber,result);
20         return result;
21     }

  4.监听结果并返回

 1 package cn.coreqi.security.async;
 2 
 3 import org.slf4j.Logger;
 4 import org.slf4j.LoggerFactory;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.context.ApplicationListener;
 7 import org.springframework.context.event.ContextRefreshedEvent;
 8 import org.springframework.stereotype.Component;
 9 import org.springframework.util.StringUtils;
10 
11 @Component
12 public class QueueListener implements ApplicationListener<ContextRefreshedEvent> {
13     @Autowired
14     private MockQueue mockQueue;    //模拟的队列
15     @Autowired
16     private DeferredResultHolder deferredResultHolder;
17 
18     private Logger logger = LoggerFactory.getLogger(getClass());
19     @Override
20     public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
21         new Thread(() -> {
22             while (true){
23                 if(StringUtils.hasText(mockQueue.getCompleteOrder())){
24                     String oderNumber = mockQueue.getCompleteOrder();   //拿到订单号
25                     logger.info("返回订单处理结果:" + oderNumber);
26                     deferredResultHolder.getMap().get(oderNumber).setResult("place order success");
27                     mockQueue.setCompleteOrder(null);
28                 }else{
29                     try {
30                         Thread.sleep(100);
31                     } catch (InterruptedException e) {
32                         e.printStackTrace();
33                     }
34                 }
35             }
36         }).start();
37     }
38 }

 ⒊异步相关配置

 1 package cn.coreqi.security.config;
 2 
 3 import org.springframework.context.annotation.Configuration;
 4 import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
 5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 6 
 7 @Configuration
 8 public class WebConfig implements WebMvcConfigurer {
 9     
10     /**
11      * 配置异步支持
12      * @param configurer
13      */
14     @Override
15     public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
16         //configurer.registerCallableInterceptors();  //设置异步的拦截器
17         //configurer.registerDeferredResultInterceptors();    //设置异步的拦截器
18         //configurer.setDefaultTimeout(20000);  //设置超时时间
19         //configurer.setTaskExecutor();   //默认情况下Spring用自己简单的异步线程池来处理,不会重用池里面的线程,
20                                         //而是每次调用时都会开启新的线程,可以自己设置一些可重用的线程池来替换
21                                         //Spring默认的简单异步线程池。
22     }
23 }
原文地址:https://www.cnblogs.com/fanqisoft/p/10612882.html