Java通过代码模拟高并发可以以最快的方式发现我们系统中潜在的线程安全性问题,此处使用Semaphore
(信号量)和 CountDownLatch
(闭锁)搭配ExecutorService
(线程池)来进行模拟
Semaphore
JDK 1.5之后会提供这个类,Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。其原理图如下:
CountDownLatch
JDK 1.5之后会提供这个类,CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
其原理图如下:
以上两个类可以搭配使用,达到模拟高并发的效果,以下使用代码的形式进行举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
public class ConcurrentCountExample {
private static final int CLIENT_TOTAL = 5000;
private static final int THREAD_TOTAL = 200;
private static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(THREAD_TOTAL); final CountDownLatch countDownLatch = new CountDownLatch(CLIENT_TOTAL); for (int i = 0;i<CLIENT_TOTAL;i++){ executorService.execute(()->{ try { semaphore.acquire(); add(); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); System.out.println("count = " + count);
}
private static void add(){ count.incrementAndGet(); }
}
|