有时候要测试一下某个功能的并发能力,又不要想借助于其他测试工具,索性就自己写简单的演示模拟一个并发请求就最方便了。如果熟悉jemter的测试某接口的并发能力其实更专业,此处只是自己折腾着玩。
CountDownLatch和CyclicBarrier是jdk并发包下非常有用的两个并发工具类,它们提供了一种控制并发流程的手段,其实查看源码它们都是在内部维护了一个计数器控制流程的
CountDownLatch:一个或者多个线程,等待其他多个线程完成某件事情之后才能执行;
CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行。
CountDownLatch和CyclicBarrier的区别
CountDownLatch的计数器,线程完成一个记录一个,计数器是递减计数器,只能使用一次
CyclicBarrier的计数器更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行,计数器是递增计数器提供重置功能,可以多次使用
另外信号可以控同时访问的线程个数,通过收购()获取一个许可,如果没有就等待,而释放()释放一个许可。
通常我们模拟并发请求,一般都是多开几个线程,发起请求就好了。但是方式,一般会存在启动的先后顺序了,算不得真正的同时并发!怎么样才能做到真正的同时并发呢?是本文想说的点,java中提供了闭锁CountDownLatch, CyclicBarrier刚好就用来做这种事就最合适了。
下面分别使用CountDownLatch和CyclicBarrier来模拟并发的请求
CountDownLatch模拟
包com.test; 引用>
进口java.io.BufferedReader;
公共类LatchTest {
进口java.io.IOException;
进口java.io.InputStream;
进口java.io.InputStreamReader;
进口java.io.OutputStream;
进口java.net.HttpURLConnection;
进口java.net.MalformedURLException;
进口java.net.URL;
进口java.util.concurrent.CountDownLatch;
<代码>公共静态void main (String [] args)抛出InterruptedException { Runnable taskTemp=new Runnable(){代码>//注意,此处是非线程安全的,留坑私人int iCounter;
<代码> @Override 公共空间run () { for (int i=0;我& lt;10;我+ +){//发起请求代码>//HttpClientOp.doGet (“https://www.baidu.com/");
iCounter + +;
System.out.println (system . nanotime () +“;[“;+ Thread.currentThread () . getname () +“] iCounter=?+ iCounter),
{
thread . sleep (100),
}捕捉(InterruptedException e) {
e.printStackTrace ();
}
}
}
};<代码> LatchTest LatchTest=new LatchTest (); latchTest。taskTemp startTaskAllInOnce(5日); } 公共长startTaskAllInOnce (int threadNums最终Runnable任务)抛出InterruptedException { 最后CountDownLatch startGate=new CountDownLatch (1); 最后CountDownLatch围板=new CountDownLatch (threadNums); for (int i=0;我& lt;threadNums;我+ +){ 线程t=新线程(){ 公共空间run () { 尝试{//使线程在此等待,当开始门打开时,一起涌入门中 startGate.await (); 尝试{ task.run (); 最后}{//将结束门减1,减到0时,就可以开启结束门了 endGate.countDown (); } }捕捉(InterruptedException ie) { ie.printStackTrace (); } } }; t.start (); } 长时间的开始时间=system . nanotime (); system . out。println(开始时间+ " " + Thread.currentThread() +”)所有线程准备好,并发去…”);//因开启门只需一个开关,所以立马就开启开始门 startGate.countDown ();//等等结束门开启 endGate.await (); 长endTime=system . nanotime (); system . out。println (endTime + " " + Thread.currentThread() +”)所有线程完成。”); 返回endTime——开始时间; }代码>}