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

⒈使用Runnable异步处理Rest服务
/**
*使用Runnable异步处理Rest服务
* @return
*/
@GetMapping("/order")
public Callable<String> callableOrder(){
logger.info("主线程开始");
System.out.println(Thread.currentThread().getId());
Callable<String> result = new Callable<String>() {
@Override
public String call() throws Exception {
logger.info("副线程开始");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getId());
logger.info("副线程返回");
return "seccess";
}
};
logger.info("主线程返回");
return result;
}
Runnable的这种形式并不能满足所有的应用场景,使用Runnable异步处理的时候,副线程必须是由主线程调起的,在实际开发的过程中,有些场景是非常复杂的。
例如,如下场景:

我们可以使用DeferredResult来解决上面复杂的场景
⒉使用DeferredResult异步处理Rest服务
1.模拟队列
package cn.coreqi.security.async; 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;
}
}
2.模拟结果
package cn.coreqi.security.async; 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<>(); //K为ID,V代表处理结果 public Map<String, DeferredResult<String>> getMap() {
return map;
} public void setMap(Map<String, DeferredResult<String>> map) {
this.map = map;
}
}
3.控制器处理
@Autowired
private MockQueue mockQueue; @Autowired
private DeferredResultHolder deferredResultHolder; /**
* 使用DeferredResult异步处理Rest服务
* @return
* @throws InterruptedException
*/
@GetMapping("/order")
public DeferredResult<String> deferredResultOrder() throws InterruptedException {
logger.info("主线程开始");
System.out.println(Thread.currentThread().getId());
String orderNumber = new Random().longs(8).toString(); //生成订单号
mockQueue.setPlaceOrder(orderNumber); //放入到消息队列里面
DeferredResult<String> result = new DeferredResult<>();
deferredResultHolder.getMap().put(orderNumber,result);
return result;
}
4.监听结果并返回
package cn.coreqi.security.async; 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;
import org.springframework.util.StringUtils; @Component
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){
if(StringUtils.hasText(mockQueue.getCompleteOrder())){
String oderNumber = mockQueue.getCompleteOrder(); //拿到订单号
logger.info("返回订单处理结果:" + oderNumber);
deferredResultHolder.getMap().get(oderNumber).setResult("place order success");
mockQueue.setCompleteOrder(null);
}else{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
⒊异步相关配置
package cn.coreqi.security.config; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
public class WebConfig implements WebMvcConfigurer { /**
* 配置异步支持
* @param configurer
*/
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
//configurer.registerCallableInterceptors(); //设置异步的拦截器
//configurer.registerDeferredResultInterceptors(); //设置异步的拦截器
//configurer.setDefaultTimeout(20000); //设置超时时间
//configurer.setTaskExecutor(); //默认情况下Spring用自己简单的异步线程池来处理,不会重用池里面的线程,
//而是每次调用时都会开启新的线程,可以自己设置一些可重用的线程池来替换
//Spring默认的简单异步线程池。
}
}
使用多线程提高Rest服务性能的更多相关文章
- 使用多线程提高REST服务器性能
异步处理REST服务 1.使用Runnable异步处理Rest服务 释放主线程,启用副线程进行处理,副线程处理完成后直接返回请求 主要代码 import java.util.concurrent.Ca ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...
- [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)
[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
[.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...
- 提高ASP.net性能的十种方法
提高ASP.net性能的十种方法 2014-10-24 空城66 摘自 博客园 阅 67 转 1 转藏到我的图书馆 微信分享: 今天无意中看了一篇关于提高ASP.NET性能的文章,个人 ...
- 25条提高iOS App性能的建议和技巧
这篇文章来自iOS Tutorial Team 成员 Marcelo Fabri, 他是 Movile 的一个iOS开发者. Check out his personal website or fol ...
- 25条提高iOS app性能的方法和技巧
以下这些技巧分为三个不同那个的级别---基础,中级,高级. 基础 这些技巧你要总是想着实现在你开发的App中. 1. 用ARC去管理内存(Use ARC to Manage Memory) 2.适当的 ...
- 25条提高iOS App性能的技巧和诀窍
25条提高iOS App性能的技巧和诀窍 当我们开发iOS应用时,好的性能对我们的App来说是很重要的.你的用户也希望如此,但是如果你的app表现的反应迟钝或者很慢也会伤害到你的审核. 然而,由于IO ...
- 根据参数优化nginx的服务性能
一.优化nginx服务的worker进程数 在高并发.高访问量的Web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求. 1).优化nginx进程对应的配置 优化n ...
随机推荐
- 微服务框架之微软Service Fabric
常见的微服务架构用到的软件&组件: docker(成熟应用) spring boot % spring cloud(技术趋势) Service Fabric(属于后起之秀 背后是微软云的驱动) ...
- day-17(基础加强)
回顾: listener(了解) 监听器,监听javaweb中三个域对象 监听对象的创建和销毁 ServletContextListener 在项目启动的时候加载配置文件 ServletRequest ...
- 解决composer出错的原因
1.执行了php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" 2.出 ...
- appcms SSRF 绕过漏洞[转载]
漏洞 <?php if(isset($_GET['url']) && trim($_GET['url']) != '' && isset($_GET['type' ...
- Javascript的作用域和闭包(一)
一.作用域是什么? 几乎所有的编程语言最基本的功能之一,就是能够存储变量的值,并且能访问和修改这些值. 修改变量值的过程我们通常在程序执行时,称为改变一个对象的状态.有了状态,让程序变得有非常有趣. ...
- [leetcode-120] 三角形最小路径和
三角形最小路径和 (1过) 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] ...
- 用IntelliJ IDEA搭建第一个SpringBoot例子
前言:最近把IntelliJ IDEA弄好了,也偶然接触到了springboot这个新的微服务框架.发现这个框架简单但也有一些不足.听说springboot可以在140个字符内发布一个web应用.所以 ...
- 解析ArcGis的标注(一)——先看看分数式、假分数式标注是怎样实现的
该“标注”系列博文的标注引擎使用“标准标注引擎(standard label engine)”,这个概念如不知道,可不理会,ArcGis默认标注引擎就是它. ArcGis的标注表达式支持VBScrip ...
- HTTP status constants
HTTP status constants value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) value = n ...
- Silverlight中字典的使用
通过值搜索字典中的项: FristOfDefault返回序列中满足条件的第一个元素:如果未找到这样的元素,则返回默认值.