⒈使用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. day05-(validate&bootstred)

    网站分享: http://www.runoob.com/ 回顾: html:展示 文件 标签: <html> <head> <title></title> ...

  2. python数据结构总结

    一.列表 1.列表脚本操作符: (1)扩增的操作符: “+”:用于组合列表:如[1,2,3]+[4,5,6]==>[1,2,3,4,5,6] "*":重复;如[2,3]*2= ...

  3. [JVM-3]Java垃圾回收(GC)机制和垃圾收集器选择

    哪些内存需要回收? 1.引用计数法 这个算法的实现是,给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1:当引用失效时,计数器值-1.任何时刻计数值为0的对象就是不可能再被使用的.这 ...

  4. springboot打包成war,部署到tomcat无法访问的问题

    如题:实在是太坑.平时本地测试觉得很方便,但是到了项目打包发布掉链子了. 如很多帖子一样: 首先springboot内嵌的tomcat,再依赖servlet-api,修改启动类继承SpringBoot ...

  5. jQuery视频格式的验证

    $(document).on('change','#videofile',function() { var file = this.files[0]; if (!/video\/\w+/.test(f ...

  6. Swagger入门

    新手入门Swagger看了很多博客,竟然没有一个是步骤齐全的或直接能运行的.于是CSDN下载了SSM+Swagger整合的demo,一顿瞎整,终于可以运行了. 不容易,因此分享这篇博客,祝新手朋友们早 ...

  7. minio golang client使用

    初始化 var ( endpoint = "127.0.0.1:8888" accessKeyID = "YXU5IXETKKPX171K4Z6O" secre ...

  8. 【1】Java中double转BigDecimal的注意事项

    项目遇到该问题 先上结论:不要直接用double变量作为构造BigDecimal的参数. 线上有这么一段Java代码逻辑: 1,接口传来一个JSON串,里面有个数字:57.3. 2,解析JSON并把这 ...

  9. bzoj 2726 任务安排(3)/loj 10184-10186 斜率优化

    任务安排1 #include<bits/stdc++.h> #define int long long using namespace std; ; int n,s,t[N],c[N],f ...

  10. webpack提示安装webpack-cli

    webpack 安装后提示CLI webpack 4X 后需要安装webpack-cli 请注意需要安装在同一目录 方法: 第一步:npm install -g webpack-cli 第二部: 同步 ...