JMeter模拟并发请求

news2024/11/25 23:03:39

        PostMan不是严格意义上的并发请求工具,实际是串行的,如果需要测试后台接口并发时程序的准确性,建议采用JMeter工具。

案例:JMeter设置20个并发卖票请求,查看后台是否存在超卖的情况

 方式一:一共10张票,票余额作为成员属性放在控制器中,没做任何的锁控制

package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
public class TicketController {

    private static int TICKET_AMOUNT = 10;//一共10张票

    @PostMapping("/sell")
    public GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析: 

从运行结果可以看出,在高并发的时候,出现了超卖和数据不一致的问题

 方式二:一共10张票,票余额作为成员属性放在控制器中,卖票的请求方法上加锁synchronized

package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
public class TicketController {

    private static int TICKET_AMOUNT = 10;//一共10张票

    @PostMapping("/sell")
    public synchronized GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析: 

 从运行结果可以看出,在高并发的时候,没有出现超卖或数据不一致问题,数据结果符合预期。

方式三:TicketController对象多例,并且TICKET_AMOUNT属性不是static,每个对象各自持有

package com.gingko.controller;
import com.gingko.common.GenericWebResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("ticket")
@Slf4j
@Scope("prototype") //多例
public class TicketController {

    private int TICKET_AMOUNT = 10;

    @PostMapping("/sell")
    public GenericWebResult sell() {
        GenericWebResult result = null;
        if(TICKET_AMOUNT > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TICKET_AMOUNT--;
            System.out.println("售票成功:余票" + TICKET_AMOUNT);
            result = GenericWebResult.ok("售票成功:余票",TICKET_AMOUNT);
        }else {
            result = GenericWebResult.error("售票失败:余票",TICKET_AMOUNT);
            System.out.println("售票失败:余票" + TICKET_AMOUNT);
        }
        return result;
    }
}

运行结果及分析:  

从程序可以看出,20个并发请求,后台生成了20个TicketController实例,每个实例内部都持有属性TICKET_AMOUNT = 10,sell方法执行后,TICKET_AMOUNT = 9

方式一、方式二与方式三示意图区别如下:

方式一、二,堆内存中只有一个TicketController实例,并且TICKET_AMOUNT不属于实例对象,属于共享的数据区,对这种共享数据并发操作时,需要锁机制控制,防止出现数据不一致。

方式三,并发请求多少,堆内存中生成多少个TicketController实例,并且每个TicketController实例各自持有TICKET_AMOUNT,访问各自的成员属性也就不会发生数据不一致问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据-177 Elasticsearch Query DSL - 聚合分析 指标聚合 桶聚合

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Excel重新踩坑3:条件格式;基本公式运算符;公式中的单元格引用方式;公式菜单栏其他有用的功能说明;

0、前言:以下内容是学习excel公式的基础内容。 1、需求:将表格特定区域中数值大小大于等于30,小于等于80的单元格,颜色填充为红色,大于80的,颜色填充为黄色。 新建规则之后也可以通过该功能清除规则。 2、基…

【JavaEE初阶】网络编程TCP协议实现回显服务器以及如何处理多个客户端的响应

前言 🌟🌟本期讲解关于TCP/UDP协议的原理理解~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不多说…

【重学 MySQL】六十六、外键约束的使用

【重学 MySQL】六十六、外键约束的使用 外键约束的概念关键字主表和从表/父表和子表外键约束的创建条件外键约束的特点外键约束的创建方式外键约束的删除外键约束的约束等级外键约束的级联操作外键约束的示例外键约束的作用开发场景阿里开发规范 在MySQL中,外键约束…

免费开源的微信开发框架

近年来,随着人工智能技术的快速发展,聊天机器人在各个领域得到了广泛的应用。在社交媒体中,自动回复成为了一个流行的功能,让用户可以方便地与机器人进行互动。gewe框架,一个开源的微信聊天机器人框架,实现…

Android 10.0 Camera2 拍照镜像功能实现

1.前言 在10.0的系统rom定制化开发中,在进行camera2的相关拍照功能开发中,在某些时候会遇到拍照照片 左右镜像的问题,就是照片左半边和右半边是反的,所以就需要在拍照的时候保存图片的时候实现 左右镜像功能,接下来就来分析下拍照保存图片的流程 2.Camera2 拍照镜像功能实…

银行数字化转型导师坚鹏:2025年银行开门红8大思考

2025年银行开门红8大思考:与2024年相比有哪些新的变化与不同? 1. ‌员工:从认清现实到重塑信心‌ 经济下行周期开启,叠加外部不稳定、不确定因素增加,让很多员工不适应、不习惯,甚至产生躺平心态。2025年…

信息学奥赛复赛复习18-CSP-J2022-01解密-二分答案、二分找边界、二分时间复杂度、二分求最小

PDF文档回复:20241017 1 P8814 [CSP-J 2022] 解密 [题目描述] 给定一个正整数 k,有 k 次询问,每次给定三个正整数 ni,ei,di,求两个正整数 pi,qi,使 nipiqi、eidi(pi−1)(qi−1)1 [输入格式] 第一行一个正整数 k,表…

leetcode动态规划(十)-0-1背包理论基础(一维数组)

一维dp数组(滚动数组) leetcode中无纯0-1背包问题,可从卡码网上查看题目46.0-1背包问题 一维数组来源于二维数组,其本质是对一维数组进行压缩了,压缩后需要注意在进行背包容量循环的时候采用后序遍历,而不…

Linux系统基础-进程间通信(3)_模拟实现匿名管道

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 Linux系统基础-进程间通信(3)_模拟实现匿名和命名管道 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论&a…

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断 目录 强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断效果一览基本介绍程序设计参考资料 效果一览 基本介绍 EEMD-MPE-KPCA-LSTM(集合经验模态分解-多尺…

无人机电机损耗!

一、电机损耗类型 机械损耗: 主要由于电机的旋转部件(如转子、轴承等)在运转过程中产生的摩擦和磨损。 长时间运行或不当维护可能加剧这种损耗。 电气损耗: 包括电阻损耗、铁芯损耗和杂散损耗等。 这些损耗主要由电流通过电…

Golang | Leetcode Golang题解之第491题非递减子序列

题目: 题解: var (temp []intans [][]int )func findSubsequences(nums []int) [][]int {ans [][]int{}dfs(0, math.MinInt32, nums)return ans }func dfs(cur, last int, nums []int) {if cur len(nums) {if len(temp) > 2 {t : make([]int, len(…

未来AI的学习能力会达到怎样的水平?

​ 大家好,我是Shelly,一个专注于输出AI工具和科技前沿内容的AI应用教练,体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具,拥抱AI时代的到来。 AI工具集1:大厂AI工具【共2…

Leetcode—192. 统计词频【中等】(Shell)

2024每日刷题(188) Leetcode—192. 统计词频 实现代码 # Read from the file words.txt and output the word frequency list to stdout. cat words.txt | tr -s \n | sort | uniq -c | sort -nr | awk {print $2, $1}运行结果 之后我会持续更新&…

学习threejs,通过THREE.Raycaster给模型绑定点击事件

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.Raycaster光线投射概…

DirectX11:Position Based Fluid

前言 这是我本科毕业设计项目,使用DirectX11实现一个基于PBD的流体模拟仿真,同时也算是补了Games101的大作业了。 阅读本文假设你对以下内容比较熟悉: 流体模拟:Smoothed Particle Hydrodynamics 流体模拟:Neighbor…

UNIX网络编程-传输层

概述 传输层主要包括:TCP、UDP、SCTP(流控制传输协议)! 绝大多数客户端/服务器网络应用都使用TCP/UDP。SCTP是一个较新的协议,最初设计用于跨因特网传输电话信令。 这些传输协议都转而使用网络协议IP:或是…

windows中命令行批处理脚本学习

目录 一 基础知识二 常见命令1. 输出 echo2. 注释 rem .... %...% :: goto if (10) ()3. 变量 set4. 获取参数 %数字 %*5. 退出 exit6. 复制 copy7.读取输出文件内容 type8. 帮助 命令xxx /?9.等待当前命令运行结束后,才执行下一条命令 call10. 修改字体编码 chcp11. 特殊变量…