Java并发编程 (三) 项目准备

傷城~ 2023-06-14 04:11 13阅读 0赞

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

一、案例环境初始化

1、环境搭建与准备

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

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

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

20191118112532398.png

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

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

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

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

20191118112725672.png

配置依赖驱动,加载项目

20191118112739328.png

二、案例准备工作

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

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

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

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

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

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

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

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

三、并发模拟 - 工具

常用工具:

Postman : Http请求模拟工具

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

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

代码: Semaphore 、CountDownLatch等

1、并发模拟——POSTMAN

20191118121223544.png

1) 创建测试接口:

  1. /**
  2. * @ClassName TestController
  3. * @Description TODO
  4. * @Author wushaopei
  5. * @Date 2019/10/30 15:48
  6. * @Version 1.0
  7. */
  8. @Controller
  9. @Slf4j
  10. public class TestController {
  11. @RequestMapping("/test")
  12. @ResponseBody
  13. public String test(){
  14. return "test";
  15. }
  16. }

使用POSTMAN模拟并发:

2) 新建测试用用户组:

20191118121428824.png

20191118121430226.png

2019111812151445.png

20191118121542973.png

20191118121548399.png

3) 执行Run Concurrency按钮:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQwNTY3MA_size_16_color_FFFFFF_t_70

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

20191118121931749.png

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

20191118122013904.png

20191118122110493.png

3、压测工具JMeter:

20191118122251904.png

jmeter文件目录下文件概览:

20191118122335419.png

启动方式:

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

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

使用界面:

20191118122621602.png

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

添加HTTP请求:

20191118122839601.png

20191118123341176.png

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

20191118123558137.png

20191118123707644.png

20191118123726435.png

20191118123810536.png

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

20191118123842615.png

请求响应结果查看:

20191118124050210.png

20191118124116370.png

四、并发模拟-代码

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

20191118124412611.png

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

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

2、Semaphore

20191118125235769.png

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

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

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

3、并发模拟

  1. package com.mmall.concurrency;
  2. import lombok.extern.slf4j.Slf4j;
  3. import java.util.concurrent.CountDownLatch;
  4. import java.util.concurrent.ExecutorService;
  5. import java.util.concurrent.Executors;
  6. import java.util.concurrent.Semaphore;
  7. /**
  8. * @ClassName ConcurrencyTest
  9. * @Description TODO
  10. * @Author wushaopei
  11. * @Date 2019/10/30 16:50
  12. * @Version 1.0
  13. */
  14. @Slf4j
  15. @NoThreadSafe //该标识表示当前线程及线程池的并发处理使用方式不正确,建议不要这么写
  16. public class ConcurrencyTest {
  17. //请求总数
  18. public static int clientTotal = 5000;
  19. // 同时并发执行的线程数
  20. public static int threadTotal = 200;
  21. public static int count = 0;
  22. public static void main(String[] args) throws InterruptedException {
  23. ExecutorService executorService = Executors.newCachedThreadPool();
  24. final Semaphore semaphore = new Semaphore(threadTotal);
  25. final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
  26. for (int i = 0 ; i < clientTotal ; i++){
  27. executorService.execute(()->{
  28. try {
  29. semaphore.acquire();
  30. add();
  31. semaphore.release();
  32. }catch (Exception e){
  33. log.error("exception",e);
  34. }
  35. countDownLatch.countDown();
  36. });
  37. }
  38. countDownLatch.await();
  39. executorService.shutdown();
  40. log.info("count:{}",count);
  41. }
  42. private static void add(){
  43. count ++;
  44. }
  45. }

执行结果:

第一次

  1. 16:58:27.063 [main] INFO com.mmall.concurrency.ConcurrencyTest - count:4944
  2. Process finished with exit code 0

第二次:

  1. 16:59:48.185 [main] INFO com.mmall.concurrency.ConcurrencyTest - count:4938
  2. Process finished with exit code 0

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

小结:

Postman : Http请求模拟工具

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

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

代码: Semaphore、CountDownLatch等

发表评论

表情:
评论列表 (有 0 条评论,13人围观)

还没有评论,来说两句吧...

相关阅读

    相关 项目准备

    商秀app 通过识别摄像头中的目标物体(此处为名片)来进行AR渲染的项目 主要采用了SIFT算法,并对其进行了优化。 我的工作:一部分的优化工作,主要是构建图像金字塔