热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

⒈使用Runnable异步处理Rest服务1**2*使用Runnable异步处理Rest服务3*return4*5GetMapping(order)6publicCallabl

⒈使用Runnable异步处理Rest服务

1 /**
2 *使用Runnable异步处理Rest服务
3 * @return
4 */
5 @GetMapping("/order")
6 public Callable callableOrder(){
7 logger.info("主线程开始");
8 System.out.println(Thread.currentThread().getId());
9 Callable result = new Callable() {
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> map &#61; new HashMap<>(); //K为ID&#xff0c;V代表处理结果
13
14 public Map> getMap() {
15 return map;
16 }
17
18 public void setMap(Map> map) {
19 this.map &#61; map;
20 }
21 }

  3.控制器处理

1 &#64;Autowired
2 private MockQueue mockQueue;
3
4 &#64;Autowired
5 private DeferredResultHolder deferredResultHolder;
6
7 /**
8 * 使用DeferredResult异步处理Rest服务
9 * &#64;return
10 * &#64;throws InterruptedException
11 */
12 &#64;GetMapping("/order")
13 public DeferredResult deferredResultOrder() throws InterruptedException {
14 logger.info("主线程开始");
15 System.out.println(Thread.currentThread().getId());
16 String orderNumber &#61; new Random().longs(8).toString(); //生成订单号
17 mockQueue.setPlaceOrder(orderNumber); //放入到消息队列里面
18 DeferredResult result &#61; 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 &#64;Component
12 public class QueueListener implements ApplicationListener {
13 &#64;Autowired
14 private MockQueue mockQueue; //模拟的队列
15 &#64;Autowired
16 private DeferredResultHolder deferredResultHolder;
17
18 private Logger logger &#61; LoggerFactory.getLogger(getClass());
19 &#64;Override
20 public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
21 new Thread(() -> {
22 while (true){
23 if(StringUtils.hasText(mockQueue.getCompleteOrder())){
24 String oderNumber &#61; mockQueue.getCompleteOrder(); //拿到订单号
25 logger.info("返回订单处理结果&#xff1a;" &#43; 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 &#64;Configuration
8 public class WebConfig implements WebMvcConfigurer {
9
10 /**
11 * 配置异步支持
12 * &#64;param configurer
13 */
14 &#64;Override
15 public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
16 //configurer.registerCallableInterceptors(); //设置异步的拦截器
17 //configurer.registerDeferredResultInterceptors(); //设置异步的拦截器
18 //configurer.setDefaultTimeout(20000); //设置超时时间
19 //configurer.setTaskExecutor(); //默认情况下Spring用自己简单的异步线程池来处理&#xff0c;不会重用池里面的线程&#xff0c;
20 //而是每次调用时都会开启新的线程&#xff0c;可以自己设置一些可重用的线程池来替换
21 //Spring默认的简单异步线程池。
22 }
23 }

 


转载于:https://www.cnblogs.com/fanqisoft/p/10612882.html


推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因
    本文介绍了解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因。其中包括修改包名、解决service name重复、处理jar包冲突和添加maven依赖等解决方案。同时推荐了一个人工智能学习网站,该网站内容通俗易懂,风趣幽默,值得一看。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
author-avatar
hgo6786689
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有