⒈使用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服务性能的更多相关文章

  1. 使用多线程提高REST服务器性能

    异步处理REST服务 1.使用Runnable异步处理Rest服务 释放主线程,启用副线程进行处理,副线程处理完成后直接返回请求 主要代码 import java.util.concurrent.Ca ...

  2. [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)

    [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...

  3. [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)

    [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...

  4. [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)

    [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...

  5. 提高ASP.net性能的十种方法

    提高ASP.net性能的十种方法 2014-10-24  空城66  摘自 博客园  阅 67  转 1 转藏到我的图书馆   微信分享:   今天无意中看了一篇关于提高ASP.NET性能的文章,个人 ...

  6. 25条提高iOS App性能的建议和技巧

    这篇文章来自iOS Tutorial Team 成员 Marcelo Fabri, 他是 Movile 的一个iOS开发者. Check out his personal website or fol ...

  7. 25条提高iOS app性能的方法和技巧

    以下这些技巧分为三个不同那个的级别---基础,中级,高级. 基础 这些技巧你要总是想着实现在你开发的App中. 1. 用ARC去管理内存(Use ARC to Manage Memory) 2.适当的 ...

  8. 25条提高iOS App性能的技巧和诀窍

    25条提高iOS App性能的技巧和诀窍 当我们开发iOS应用时,好的性能对我们的App来说是很重要的.你的用户也希望如此,但是如果你的app表现的反应迟钝或者很慢也会伤害到你的审核. 然而,由于IO ...

  9. 根据参数优化nginx的服务性能

    一.优化nginx服务的worker进程数 在高并发.高访问量的Web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求. 1).优化nginx进程对应的配置 优化n ...

随机推荐

  1. ELK-6.5.3学习笔记–使用filebeat管理微服务日志

    微服务日志打印. 转载于http://www.eryajf.net/2369.html 上边是输出了nginx日志,从而进行展示,以及各种绘图分析,而现在的需求是,要将微服务当中的日志汇总到elk当中 ...

  2. 黑苹果是否会成为mac电脑的竞争对手?

    最近黑科技技术大佬们都在传扬windows系统上安装mac系统,不用买mac电脑也可以使用mac一样的操作环境.什么是黑苹果?一起来看看如何在windows系统上安装mac系统. 更多专题,可关注小编 ...

  3. Tensorflow object detection API 搭建物体识别模型(二)

    二.数据准备 1)下载图片 图片来源于ImageNet中的鲤鱼分类,下载地址:https://pan.baidu.com/s/1Ry0ywIXVInGxeHi3uu608g 提取码: wib3 在桌面 ...

  4. docker 私有仓库之Harbor搭建与使用

    Harbor搭建 下载Harbor: http://harbor.orientsoft.cn/ #下载offline版本 配置Harbor tar xvf harbor-online-installe ...

  5. centos 6 与 centos 7 服务开机启动、关闭设置的方法

    简单说明下 centos 6 与 centos 7 服务开机启动.关闭设置的方法: centos 6 :使用chkconfig命令即可. 我们以apache服务为例: #chkconfig --add ...

  6. linux 配置本地光盘YUM源

    1.挂载光盘到 /media下 [root@localhost ~]# mount /dev/cdrom /media 2.直接配置文件了. [root@localhost ~]# cd /etc/y ...

  7. win7安装linux CentOS7双系统实践

    开发需求要安装linux,百度了些资料,当然仅供参考,否则入坑. 步骤一 :制作Centos 7镜像文件,这步没什么坑 1.准备U盘8G以上 下载的话网上很多,这里提供一个下载路径:​ http:// ...

  8. mysql导入导出sql文件,source导入速度慢的解决办法

    1.导出整个数据库mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -u dbuser -p dbname > dbname.sql2.导出一个表mys ...

  9. ASP.NET MVC 4 笔记

    1.   MVC2.MV3.MC4 的区别 1)   MVC2 1.   View 文件以*.aspx结尾,为原始html页面内容. 2.   View 代码以<%代码-结束%>. 2)  ...

  10. Hero Patterns - 聚合各种 SVG 背景纹理素材的网站

    Hero Patterns 是一个聚合了各种 SVG 背景纹理素材的网站,提供的多样的素材可以给你的网站带去特色. SVG 是一种分辨率无关的图形(矢量图形).这意味着它在任何类型的屏幕都不会遭受任何 ...