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