个人博客网:https://wushaopei.github.io/    (你想要这里多有)

一、案例环境初始化

1、环境搭建与准备

Spring Boot 项目,https://start.spring.io/

Git 管理代码,https://github.com/wushaopei/concurrency

码云:https://gitee.com/wushaopei

点击Generate -Ctrl + 将项目下载到本地,并解压。

使用git bash 将码云仓库下载到本地:

git clone https://gitee.com/wushaopei/concurrency.git

将concurrency.zip压缩包解压后的src、mvnw.cmd、mvnw、pom.xml文件复制到git仓库目录concurrency下,

配置依赖驱动,加载项目

二、案例准备工作

1、自定义注解ThreadSafe.java类,用于标识线程安全的类:

/**
* @ClassName ThreadSafe
* @Description TODO
* @Author wushaopei
* @Date 2019/10/30 14:39
* @Version 1.0
* 用来标记线程安全的类或写法
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ThreadSafe { String value() default "";
}

2、自定义注解NoThreadSafe.java类,用于标识线程不安全的类:

/**
* @ClassName NoThreadSafe
* @Description TODO
* @Author wushaopei
* @Date 2019/10/30 14:44
* @Version 1.0
* 用来标记线程不安全的类或写法
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NoThreadSafe { String value() default "";
}

3、用来标记 不推荐 的类或者写法

/**
* 用来标记 不推荐 的类或者写法
* */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NoRecommend { String value() default "";
}

4、Recommend.java 用来标记 推荐 的类或者写法

/**
* 用来标记 推荐 的类或者写法
* */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Recommend { String value() default "";
}

三、并发模拟 - 工具

常用工具:

Postman : Http请求模拟工具

Apache Bench AB) : Apache附带的工具,测试网站性能

JMeter : Apache 组织开发的压力测试工具

代码: Semaphore 、CountDownLatch等

1、并发模拟——POSTMAN

1) 创建测试接口:

/**
* @ClassName TestController
* @Description TODO
* @Author wushaopei
* @Date 2019/10/30 15:48
* @Version 1.0
*/
@Controller
@Slf4j
public class TestController { @RequestMapping("/test")
@ResponseBody public String test(){
return "test";
}
}

使用POSTMAN模拟并发:

2) 新建测试用用户组:

3) 执行Run Concurrency按钮:

2、使用专业并发模拟测试工具——Apache Bench(AB)

使用ab命令指定每秒的请求数和间隔时间以及请求接口地址

3、压测工具JMeter:

jmeter文件目录下文件概览:

启动方式:

linux环境使用jmeter.sh启动脚本测试

Windows环境使用jmeter.bat启动脚本测试

使用界面:

Ramp-Up Period 代表虚拟用户增长时长,可理解为一段时间内多个用户登录的总时间范围,如8点15到9点这段时间是打卡上班的时间,也就是45分钟*60秒=2700秒

添加HTTP请求:

添加监听窗口-图形结果和察看结果树

点击绿色三角按钮启动HTTP请求

请求响应结果查看:

四、并发模拟-代码

1、 CountDownLatch (计数器向下减的闭锁)

案例解析该类的使用: 假设计数器值 cnt = 3, 线程A在调用了await()方法之后,当前线程就进入了等待状态awaiting;之后在其他进程中每次执行countDown()方法(如T1)之后计数器 cnt 就会减一,然后当前线程继续执行;之后的T2、T3一次执行完成,当计数器 cnt 变成 0之后,线程A才会继续执行。

说明: CountDownLatch这个类可以阻塞线程,并在满足某种特定条件下去执行。

2、Semaphore

假如一条公路上只有两条车道,那么同时只有两辆车可以通过同一个点;当两辆车中的其中一辆车让开以后,其他的等待的车就可以继续通过了。

说明: Semaphore可以阻塞进程,并且可以控制同一时间请求的并发量

CountDownLatch 和 Semaphore 通常会和线程池一起使用

3、并发模拟

package com.mmall.concurrency;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; /**
* @ClassName ConcurrencyTest
* @Description TODO
* @Author wushaopei
* @Date 2019/10/30 16:50
* @Version 1.0
*/
@Slf4j
@NoThreadSafe //该标识表示当前线程及线程池的并发处理使用方式不正确,建议不要这么写
public class ConcurrencyTest { //请求总数
public static int clientTotal = 5000; // 同时并发执行的线程数
public static int threadTotal = 200; public static int count = 0; public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0 ; i < clientTotal ; i++){
executorService.execute(()->{
try {
semaphore.acquire();
add();
semaphore.release();
}catch (Exception e){
log.error("exception",e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}",count);
} private static void add(){
count ++;
}
}

执行结果:

第一次

16:58:27.063 [main] INFO com.mmall.concurrency.ConcurrencyTest - count:4944

Process finished with exit code 0

第二次:

16:59:48.185 [main] INFO com.mmall.concurrency.ConcurrencyTest - count:4938

Process finished with exit code 0

由结果可知:程序执行结果数量少于5000,并且每次都不同。所以这是不确定的结果,存在线程安全的问题。

小结:

Postman : Http请求模拟工具

Apache Bench(AB):Apache附带的工具,测试网站性能

JMeter : Apache组织开发的压力测试工具

代码: Semaphore、CountDownLatch等

最新文章

  1. Python基础2:流程控制语句 while / for循环
  2. Android杂谈--Activity、Window、View的关系
  3. go对json的解析处理
  4. Oracle 表的连接方式(2)-----HASH JOIN的基本机制3
  5. MyBatis之六:缓存
  6. Delphi对ini文件的操作
  7. js 模板引擎
  8. SQL Server数据库优化的10多种方法
  9. javaScript设计模式之----工厂模式
  10. ZYNQ基础知识一
  11. 关于让simulink中display组件显示二进制的方法
  12. Error response from daemon: --cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode
  13. Dubbo x Cloud Native 服务架构长文总结(很全)
  14. dubbo系列一、dubbo背景介绍、微服务拆分
  15. Codeforces 1102F Elongated Matrix 状压dp
  16. django的模板语言中一些之前没有用过的小点
  17. 迪米特法则(Law Of Demeter)
  18. Java之集合(二十四)ConcurrentLinkedDeque
  19. Git知多少!!!
  20. abp项目如何按业务功能模块横向分割?

热门文章

  1. 【Spark】一起了解一下大数据必不可少的Spark吧!
  2. 接口测试/soapUI
  3. jconsole+idea监控+(jvisualvm 本地内存分析)
  4. vue中v-for索引不要用key
  5. 汉语拼音转换工具包pypinyin
  6. GeoServer2.17与Jetty9在Windows上的最佳安装实践
  7. Java Number &amp; Math类
  8. javascript代码重构需要考虑的问题(一)
  9. ios时间显示NaN
  10. tp5增删改查基本操作