https://www.jianshu.com/p/46444637dd68
思路
第一种:线程池模拟200个线程——wait等待线程数达200——notifyAll唤醒所有线程
第二种:线程池模拟200个线程——阻塞线程——达到200条件释放
比较
两种方案都可以实现瞬时高并发的模拟,但是建议使用第二种方案。
第一种方案中,压测过程中,wait状态下的线程已经释放对象上的锁定,唤醒时会极大的消耗CPU资源。压测程序可能直接导致机器崩溃
第二种方案,由于阻塞过程中,线程不会释放掉目前持有的对象资源,因此等待条件释放不会造成资源的过度消耗。
但是应当选择好阻塞方式,避免线程操作时的死锁。同时实现线程之间的通信。
wait-notifyAll
代码较简单,通过线程池启动1000个线程,通过synchronized保证线程可见性,和安全性。
当线程数量未达到1000时,wait使线程退出CPU,释放锁。
当线程数量达到1000时,notifyAll通知等待集上的线程,唤醒线程。
代码如下:
计数类:
import lombok.Data;
@Data
public class Counts {
public Integer num;
}
执行类:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Parallellimit {
public static void main(String[] args){
ExecutorService pool = Executors.newCachedThreadPool();
Counts count = new Counts();
//共享操作该计数变量,不能使用int或者integer,Java无法对非对象、和包装
//类进行加锁
count.num = 0;
for(int i=0;i<100;i++){ //启动线程
MyRunnable runnable = new MyRunnable(count);
pool.execute(runnable);
}
pool.shutdown();//关闭线程池,无法加入新线程任务,但不影响现有线程
}
}
实现类:
public class MyRunnable implements Runnable {
private Counts count ;/*** 通过构造方法传入初值,避免set和get时线程的不安全性*/
public MyRunnable(Counts count){
this.count = count;
}
public void run(){
try{ /*** 加锁,保证线程可见性和安全性*/
synchronized (count){
count.num ++;
if(count.num < 100){
System.out.println(count);
count.wait();
}
/*** 达到10000时唤醒 所有线程 */
if(count.num == 100){
count.notifyAll();
System.out.println("并发量 count="+count);
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
CountDownLatch
Java提供的实现阻塞和释放线程的类,尝试是否符合推荐的规律。其中主要包含三个方法countDownLatch(100) 类通过构造方法传入计数数量。countDown() 方法会减少一个计数值await() 方法自动阻塞线程,直到count的值变为0执行过程中,同步操作count后,开始等待,直到100个线程全部创建后并发执行代码如下
执行类:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Parallellimit {
public static void main(String[] args){
ExecutorService pool = Executors.newCachedThreadPool();
CountDownLatch count = new CountDownLatch(1000);
for(int i=0;i<1000;i++){ //启动线程7
MyRunnable runnable = new MyRunnable(count);
pool.execute(runnable);
}
pool.shutdown();
}
}
实现类
import java.util.concurrent.CountDownLatch;
public class MyRunnable implements Runnable {
private CountDownLatch count ;/*** 通过构造方法传入初值,避免set和get时线程的不安全性*/
public MyRunnable(CountDownLatch count){
this.count = count;
}
public void run(){
try{ /*** 不加锁也可以支持,虽然打印出的值不对,但最后计算次数却是100次* 说明确实是执行了整整
100次才并发,计算次数正确*/
synchronized (count){
/*** 每次减少一个容量*/
count.countDown();
System.out.println("thread counts = "+(count.getCount()));
System.out.println("concurrency counts = "+(100-count.getCount()));
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}