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

异步处理REST服务

1、使用Runnable异步处理Rest服务

释放主线程,启用副线程进行处理,副线程处理完成后直接返回请求

主要代码

import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 *
 * @author hzc
 *
 */
@RestController
public class AsyncController {

    private Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @RequestMapping("/order")
    public Callable order() throws InterruptedException {
        logger.info("主线程开始");

        Callable result = new Callable() {

            @Override
            public String call() throws Exception {
                logger.info("副线程开始");
                Thread.sleep(1000);
                logger.info("副线程结束");
                return "success";
            }

        };
        logger.info("主线程返回");
        return result;

    }
}

2、使用DeferredResult异步处理Rest服务

释放主线程,启用副线程1进行前处理,副线程2进行后处理,副线程2处理完后返回请求

模拟业务场景

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

主线程调用副线程1进行业务处理,将任务放于消息队列,副线程2监听消息队列,并处理队列的任务,在使用DeferredResult获取队列返回的结果,返回给前端

Controller类

package com.maple.security.web.async;

import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

/**
 *
 * @author hzc
 *
 */
@RestController
public class AsyncController {

    private Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @Autowired
    private MockQueue mockQueue;

    @Autowired
    private DeferredResultHolder deferredResultHolder;

    @RequestMapping("/order")
    public DeferredResult order() throws InterruptedException {
        logger.info("主线程开始");

        String orderNumber = RandomStringUtils.randomNumeric(8);
        mockQueue.setPlaceOrder(orderNumber);

        DeferredResult result = new DeferredResult<>();
        deferredResultHolder.getMap().put(orderNumber, result);
        logger.info("主线程返回");
        return result;

    }
}

模拟消息队列类

package com.maple.security.web.async;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 *
 * @author hzc
 *
 */
@Component
public class MockQueue {

    private Logger logger = LoggerFactory.getLogger(MockQueue.class);

    // 生成下单
    private String placeOrder;

    // 完成下单
    private String completeOrder;

    public String getPlaceOrder() {
        return placeOrder;
    }

    public void setPlaceOrder(String placeOrder) {
        new Thread(() -> {
            logger.info("接到下单请求");
            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;
    }
}

监听消息队列并处理类

package com.maple.security.web.async;

import org.apache.commons.lang.StringUtils;
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;

@Component
public class QueueListener implements ApplicationListener {

    private Logger logger = LoggerFactory.getLogger(QueueListener.class);

    @Autowired
    private MockQueue mockQueue;

    @Autowired
    private DeferredResultHolder deferredResultHolder;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        new Thread(() -> {
            while (true) {
                if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())) {
                    String orderNumber = mockQueue.getCompleteOrder();
                    logger.info("返回订单处理结果:" + orderNumber);
                    deferredResultHolder.getMap().get(orderNumber).setResult("place order success");

                    mockQueue.setCompleteOrder(null);

                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }
}

异步处理结果类

/**
 *
 */
package com.maple.security.web.async;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * @author hzc
 *
 */
@Component
public class DeferredResultHolder {

    private Map> map = new HashMap>();

    public Map> getMap() {
        return map;
    }

    public void setMap(Map> map) {
        this.map = map;
    }

}

3、异步处理配置

Original: https://www.cnblogs.com/maple92/p/11616472.html
Author: Topze
Title: 使用多线程提高REST服务器性能

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582938/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 怎么实现Redis的高可用?(主从、哨兵、集群)

    高可用有两个含义: 一是数据尽量不丢失,二是保证服务尽可能可用。 AOF 和 RDB 数据持久化保证了数据尽量不丢失,那么多节点来保证服务尽可能提供服务。 一般在实际生产中,服务不…

    Linux 2023年5月28日
    084
  • C++复制构造函数,类型转换构造函数,析构函数,引用,指针常量和常量指针

    复制构造函数形如className :: className(const &) / className :: className(const className &…

    Linux 2023年6月7日
    077
  • 读软件测试艺术感悟

    断断续续的看,总觉得好像是漏掉了什么,而且一直 想着还有什么事情未做,却静不下心来去细品 开篇用自测评价测试,举例三角形例子写出等价类边界值的方法给测试人员举一个例子,更好的使测试…

    Linux 2023年6月8日
    092
  • Laxcus集群操作系统桌面图标优化和算法

    泰山不拒细壤,故能成其高;江海不择细流,故能成其深。全抱之末生于毫末,九层之台起于累土,千里之行始于足下。 任何一个完善成熟的产品,都是从微小的改进开始! Laxcus集群操作系统…

    Linux 2023年6月6日
    084
  • SpringBoot-shiro

    SpringBoot-shiro 12.1 快速入门 1、导入依赖 org.apache.shiro shiro-core 1.8.0 org.slf4j jcl-over-slf…

    Linux 2023年6月14日
    096
  • python openpyxl UserWarning: Workbook contains no default style, apply openpyxl‘s default

    告警解释 这是一个告警,这个excel文件没有设置默认的样式。一般这种没有默认样式的excel文档是由java程序生成的,不是像windows系统日常使用中通过右键点击创建的exc…

    Linux 2023年6月8日
    084
  • Dockerfile 使用 SSH docker build

    如果在书写 Dockerfile 时,有些命令需要使用到 SSH 连接,比如从私有仓库下载文件等,那么我们应该怎么做呢? Dockerfile 文件配置 为了使得 Dockerfi…

    Linux 2023年6月7日
    078
  • IDEA生成带参数和返回值注释

    步骤说明 打开IDEA进入点击左上角 – 文件 – 设置 – 编辑器 – 活动模板 新建活动模板 填写模板文本 编辑变量 添加变量表…

    Linux 2023年6月6日
    097
  • 【原创】Linux虚拟化KVM-Qemu分析(七)之timer虚拟化

    背景 Read the fucking source code! –By 鲁迅 A picture is worth a thousand words. –…

    Linux 2023年6月8日
    098
  • Linux指令_曾佳豪

    一、基础指令 1、ls指令 含义:ls (list) 用法1 :#ls 含义:列出当前工作目录下所有文件/文件夹的名称 [En] Meaning: list the names o…

    Linux 2023年5月27日
    0114
  • 让SpringBoot也用上Fluent Validator

    前言 在使用SpringBoot的时候经常需要对客户端传入的参数进行合法性的校验,校验的方法基本上都是使用SpringBoot提供的注解,有时候遇上注解不能满足需求的时候还需要在业…

    Linux 2023年6月14日
    084
  • ssh远程连接服务(二)三台虚拟机之间的免密登录

    创建三台虚拟机主机名分别为node01、node02、node03 在node01虚拟机上生成密钥对 然后将生成的公钥分别复制到node02、node03的虚拟机上(前提三台虚拟机…

    Linux 2023年6月7日
    095
  • 树莓派4B串口测试与开发

    树莓派4B的串口,由两个增加4个,一共6个! 情况一: 缺省镜像中的配置,测试发现只启用了2个:pi@raspi4b:~ $ ls -l /dev/serial*lrwxrwxrw…

    Linux 2023年6月7日
    073
  • Ubuntu无法telnet

    (1)/etc/hosts被修改过 (2)防火墙没有关闭 (3)没有安装相关服务 (4)/etc/inetd.conf文件没有telnet相关内容 (1)把/etc/hosts文件…

    Linux 2023年6月8日
    091
  • select,poll,epoll的区别以及使用方法

    I/O多路复用是指:通过一种机制,可以 监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。 原生socket客户端在与服务端建立连接时,…

    Linux 2023年6月14日
    091
  • 多线程核心基础

    1 进程和线程 ​ 进程是OS分配资源的最进本的单位,线程是执行调度的最基本单位。分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己的独立空间)。J…

    Linux 2023年6月14日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球