• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

你会用Java代码模拟高并发吗

java 搞代码 4年前 (2022-01-09) 14次浏览 已收录 0个评论

Java通过代码模拟高并发可以以最快的方式发现我们系统中潜在的线程安全性问题,此处使用Semaphore(信号量)和 CountDownLatch(闭锁)搭配ExecutorService(线程池)来进行模拟,主要介绍如下:

1、Semaphore

JDK 1.5之后会提供这个类

Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。

2、CountDownLatch

JDK 1.5之后会提供这个类,

CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。

本文来源gaodaimacom搞#^代%!码网@CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

如下图:

以上两个类可以搭配使用,达到模拟高并发的效果,以下使用代码的形式进行举例:

package modules; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Semaphore; 
public class CountExample { 
 // 请求总数 
 public static int clientTotal = 5000; 
 // 同时并发执行的线程数 
 public static int threadTotal = 200; 
 public static int count = 0; 
 public static void main(String[] args) throws Exception { 
 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 { 
  //执行此方法用于获取执行许可,当总计未释放的许可数不超过200时, 
  //允许通行,否则线程阻塞等待,直到获取到许可。 
 semaphore.acquire(); 
 add(); 
 //释放许可 
 semaphore.release(); 
 } catch (Exception e) { 
 //log.error("exception", e); 
 e.printStackTrace(); 
 } 
 //闭锁减一 
 countDownLatch.countDown(); 
 }); 
 } 
 countDownLatch.await();//线程阻塞,直到闭锁值为0时,阻塞才释放,继续往下执行 
 executorService.shutdown(); 
 log.info("count:{}", count); 
 } 
 private static void add() { 
 count++; 
 } 
} 

如上方法模拟5000次请求,同时最大200个并发操作,观察最后的结果,发现每次的结果都有差别,和预期不符,得出结果部分如下:

22:18:26.449 [main] INFO modules.CountExample – count:4997
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:4995
22:18:26.449 [main] INFO modules.CountExample – count:4998

最后结论:add 方法 非线程安全

那如何保证add方法 线程安全,将add方法进行如下修改即可:

private static void add() { 
 count.incrementAndGet(); 
} 

执行结果如下:

22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000
22:18:26.449 [main] INFO modules.CountExample – count:5000

最后结论:修改后 的 add 方法 线程安全

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:你会用Java代码模拟高并发吗

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址