有时需要测试一下某个功能的并发性能,又不要想借助于其他工具,索性就自己的开发语言,来一个并发请求就最方便了。
java中模拟并发请求,自然是很方便的,只要多开几个线程,发起请求就好了。但是,这种请求,一般会存在启动的先后顺序了,算不得真正的同时并发!怎么样才能做到真正的同时并发呢?是本文想说的点,java中提供了闭锁 CountDownLatch, 刚好就用来做这种事就最合适了。
只需要:
-
开启n个线程,加一个闭锁,开启所有线程;
-
待所有线程都准备好后,按下开启按钮,就可以真正的发起并发请求了。
package com.zx.demo.countDownLatch; import com.zx.demo.util.JedisClusterUtil; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.util.concurrent.CountDownLatch; @SpringBootTest public class CountDownLacthTest { @Test public void testRedisLock() throws InterruptedException { //同时并发5个请求 startTaskAllInOnce(5); } public long startTaskAllInOnce(int threadNums) throws InterruptedException { //一个开启开关(一次开启,多个线程一起开始) final CountDownLatch startGate = new CountDownLatch(1); //一个关闭开关(多次结束,多个线程分别结束) final CountDownLatch endGate = new CountDownLatch(threadNums); for(int i = 0; i < threadNums; i++) { Thread t = new Thread(() -> { try { //开启开关未打开,所有new子线程的执行在此处阻塞,等待开启开关打开时,一起并发执行 startGate.await(); try { //调起线程 new Thread(new Runnable() { @Override public void run() { System.out.println("子线程名:"+Thread.currentThread().getName()+"开始执行"+System.currentTimeMillis()); //下面写要并发的接口请求即可 } }).run(); } finally { //当前子线程执行结束,将关闭开关线程数减一,减到零时,关闭开关打开 endGate.countDown(); } } catch (InterruptedException ie) { ie.printStackTrace(); } }); t.start(); } //记录多线程开始执行时间 long startTime = System.nanoTime(); System.out.println(startTime + " [" + Thread.currentThread().getName() + "] All thread is ready, concurrent going..."); //主线程将开启开关线程数减一,因初始值为1,直接减到零了,开启开关打开,上面阻塞的各子线程并发执行 startGate.countDown(); //关闭开关未打开,使当前主线程阻塞在此,等待上方多个子线程执行,当所有子线程执行完毕,关闭开关线程数减到零,关闭开关打开,继续执行主线程 endGate.await(); //记录多线程执行结束时间 long endTime = System.nanoTime(); System.out.println(endTime + " [" + Thread.currentThread().getName() + "] All thread is completed."); return endTime - startTime; } }
执行效果