模拟多线程高并发进行压力测试

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();
		}
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章