模擬多線程高併發進行壓力測試

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

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