⒈使用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. cmd解压压缩包

    需要安装有winrar start winrar x C:\Users\systme\Desktop\xxx.rar c:\123

  2. M1-Flask-Day1

    前情概要 1.flask的基本使用 - 配置 - 路由 - 视图 - 请求与响应相关 - 模板 2.flask基于装饰器实现的路由 - 基本操作 - functools - 带参数的装饰器 - 源码剖 ...

  3. CentOS6.9快速安装配置svn

    CentOS6.9快速安装配置svn 环境介绍: 操作系统:CentOS release 6.9 (Final)192.168.65.130 (svn服务器)192.168.65.129 (svn客户 ...

  4. Advertising.csv

    TV,radio,newspaper,sales1,230.1,37.8,69.2,22.12,44.5,39.3,45.1,10.43,17.2,45.9,69.3,9.34,151.5,41.3, ...

  5. 简洁架构的思想,基于go实现

    https://manuel.kiessling.net/2012/09/28/applying-the-clean-architecture-to-go-applications/ 从 Clean- ...

  6. Pycharm搭建Django开发环境

    Pycharm搭建Django开发环境 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们大家都知道Django是python都一个web框架,因此大家需要自行安装python环境 ...

  7. Hadoop问题:There are 0 datanode(s) running and no node(s) are excluded in this operation.

    问题描述: org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /tmp/hadoop-yarn/staging/hado ...

  8. Trap 冷启动与热启动告警

    冷启动: 设备断电重启. 热启动: snmp agent 从未使能到使能的操作会产生此告警.

  9. Golang入门教程(三)beego 框架安装

    beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API.Web 及后端服务等各种应用,是一个 RESTful 的框架,主要设计灵感来源于 tornado.sinatra ...

  10. 在Linux(CentOS 6.6)服务器上安装并配置基于Apache的SVN服务器

    #!/bin/bash # # 在Linux(CentOS 6.6)服务器上安装并配置基于Apache的SVN服务器: # # .安装服务 # .创建svn版本库 # .创建svn用户 # .配置sv ...