⒈使用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. BZOJ2815 拓扑排序 + LCA

    https://www.lydsy.com/JudgeOnline/problem.php?id=2815 作为一个DAG图,结点之间又有这么明显的等级之分,很容易想到的是拓扑排序. 但是不管是正向的 ...

  2. springboot启动报错Failed to configure a DataSource

    2018-11-21 19:43:12.076 WARN 5392 --- [ main] ConfigServletWebServerApplicationContext : Exception e ...

  3. 2017-12-15python全栈9期第二天第五节之格式化输出补充之想要在格式化输出中表示单纯的%号就加%

    #!/user/bin/python# -*- coding:utf-8 -*-name = input('姓名:')age = input('年龄:')height = input('身高:')ms ...

  4. Java Web之Tomcat

    Tomcat的下载安装配置什么的,百度一大把.现在介绍一下Tomcat的文件夹目录结构. 浏览器访问127.0.0.1:8080 出现Tomcat页面即表示安装成功. 这个就是Tomcat的目录了 b ...

  5. UDP中的sendto 与recvfrom

    sendto 头文件: #include <sys/types.h>   #include <sys/socket.h> 定义函数: int sendto(int s, con ...

  6. Windows2012 要远程登录,你需要具有通过远程桌面服务进行登录的权限.

    直接说正题... 提示如下: 解决办法: gpedit进入策略组:计算机配置->Windows设置->安全设置->本地策略->用户权限分配,找到拒绝通过远程桌面服务登录,把里面 ...

  7. golang命令行参数

    os.Args获取命令行参数 os.Args是一个srting的切片,用来存储所有的命令行参数 package main import ( "fmt" "os" ...

  8. Leetcode 136 Single Number 仅出现一次的数字

    原题地址https://leetcode.com/problems/single-number/ 题目描述Given an array of integers, every element appea ...

  9. CentOS7 安装 Tomcat8

    安装 Java8准备更新软件yum update 如果提示没有 wget 命令,那么必须先安装 wget 如下:yum install wget 安装Tomcat8这里采用离线解压tar.gz的方式安 ...

  10. JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理

    本文记录: 1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败. 2 ...