java 并发测试main方法_Java并发测试
要求:模擬200個設(shè)備,盡量瞬間并發(fā)量達(dá)到200。
思路
第一種:線程池模擬200個線程——wait等待線程數(shù)達(dá)200——notifyAll喚醒所有線程
第二種:線程池模擬200個線程——阻塞線程——達(dá)到200條件釋放
比較
兩種方案都可以實現(xiàn)瞬時高并發(fā)的模擬,但是建議使用第二種方案。
第一種方案中,壓測過程中,wait狀態(tài)下的線程已經(jīng)釋放對象上的鎖定,喚醒時會極大的消耗CPU資源。壓測程序可能直接導(dǎo)致機(jī)器崩潰
第二種方案,由于阻塞過程中,線程不會釋放掉目前持有的對象資源,因此等待條件釋放不會造成資源的過度消耗。
但是應(yīng)當(dāng)選擇好阻塞方式,避免線程操作時的死鎖。同時實現(xiàn)線程之間的通信。
wait-notifyAll
代碼較簡單,通過線程池啟動1000個線程,通過synchronized保證線程可見性,和安全性。
當(dāng)線程數(shù)量未達(dá)到1000時,wait使線程退出CPU,釋放鎖。
當(dāng)線程數(shù)量達(dá)到1000時,notifyAll通知等待集上的線程,喚醒線程。
代碼如下:
/**
* @author:???? irvingyuan
* @since?????? 2017年1月22日 下午4:51:51
* @version:
*/
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Counts count = new Counts(); ?//共享操作該計數(shù)變量,不能使用int或者integer,Java無法對非對象、和包裝類進(jìn)行加鎖wait
count.num = 0;
for(int i=0;i<10000;i++){ ? ? //啟動線程
MyRunnable runnable = new MyRunnable(count);
pool.execute(runnable);
}
pool.shutdown(); ? ? //關(guān)閉線程池,無法加入新線程任務(wù),但不影響現(xiàn)有線程
}
}
public class MyRunnable implements Runnable{
private Counts count ;
/**
* 通過構(gòu)造方法傳入初值,避免set和get時線程的不安全性
*/
public MyRunnable(Counts count){
this.count = count;
}
public void run() {
try {
/**
* 加鎖,保證線程可見性和安全性
*/
synchronized (count) {
count.num++;
if(count.num<10000){
System.out.println(count.num);
count.wait();//一定要調(diào)用count對象的wait,默認(rèn)對this,無法持有線程的鎖,拋出異常
}
/**
* 達(dá)到10000時喚醒所有線程
*/
if(count.num == 10000){
count.notifyAll();
}
System.out.println("并發(fā)量 count="+count.num);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
測試結(jié)果
并發(fā)喚醒1000個線程時,CPU瞬時使用率瞬時增長17%左右??梢奀PU負(fù)擔(dān)很大。
繼續(xù)增大線程數(shù),JVM拋OOM異常退出,需要修改啟動參數(shù)
block阻塞方式
同步代碼塊持有count的鎖,保證創(chuàng)建出正確的線程數(shù)量。判斷不夠并發(fā)量時,使用while阻塞線程。
當(dāng)達(dá)到并發(fā)量時,阻塞條件失效,線程繼續(xù)運行。
代碼如下:
/**
* 阻塞方式創(chuàng)建瞬時高并發(fā)
* @author:???? irvingyuan
* @since?????? 2017年1月23日 下午4:45:56
* @version:
*/
public class BlockRunnable implements Runnable{
private Counts count ;
/**
* 通過構(gòu)造方法傳入初值,避免set和get時線程的不安全性
*/
public BlockRunnable(Counts count){
this.count = count;
}
public void run() {
/**
* this肯定失效,this調(diào)用處為runnable對象
* 此時加鎖表示多個線程只能有一個線程在某時刻操作該runnable
* new出來了n個線程,自己調(diào)用自己的,this必定失效
* synchronized (this) {
*/
synchronized (count) {
count.num++;
System.out.println("Thread count = "+count.num);
}
/**
* 注意synchronized的粒度
* while放在代碼快中會導(dǎo)致線程一直持有鎖等待,下一個線程無法生成和進(jìn)行
*/
while(count.num<100);
//并發(fā)操作
System.out.println("concurrency count = "+count.num);
}
}
測試效果
100個線程瞬時的CPU使用率居然激增到了100%,和資料說的完全想法,更加損耗系統(tǒng)資源。(是不是因為while?)
//原文使用sleep,個人認(rèn)為時間不好掌握,用while直接長時間做條件阻塞
CountDownLatch
Java提供的實現(xiàn)阻塞和釋放線程的類,嘗試是否符合推薦的規(guī)律。
其中主要包含三個方法
countDownLatch(100)?????類通過構(gòu)造方法傳入計數(shù)數(shù)量。
countDown()?????方法會減少一個計數(shù)值
await()?????方法自動阻塞線程,直到count的值變?yōu)?
執(zhí)行過程中,同步操作count后,開始等待,直到100個線程全部創(chuàng)建后并發(fā)執(zhí)行
代碼如下
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
Counts count = new Counts();
count.num = 0;
CountDownLatch cdl = new CountDownLatch(100);
for(int i=0;i<100;i++){
CountRunnable runnable = new CountRunnable(cdl);
pool.execute(runnable);
}
}
}
/**
* 〈countDownlatch實現(xiàn)高并發(fā)〉
* @author:???? irvingyuan
* @since?????? 2017年1月23日 下午5:45:59
* @version:
*/
public class CountRunnable implements Runnable {
private CountDownLatch countDownLatch;
public CountRunnable(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
public void run() {
try {
/**
* 不加鎖也可以支持,雖然打印出的值不對,但最后計算次數(shù)卻是100次
* 說明確實是執(zhí)行了整整100次才并發(fā),計算次數(shù)正確
*/
synchronized (countDownLatch) {
/**
* 每次減少一個容量
*/
countDownLatch.countDown();
System.out.println("thread counts = "+(countDownLatch.getCount()));
}
/**
* 阻塞線程,直到countDown至0
*/
countDownLatch.await();
System.out.println("concurrency counts = "+(100-countDownLatch.getCount()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
測試結(jié)果
CPU增長率大約10%左右,相對于wait-notify方式要減少約一半。
綜上,阻塞似乎是最坑爹的一種方式
總結(jié)
以上是生活随笔為你收集整理的java 并发测试main方法_Java并发测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php输出楼层号,ZBlog开发中实现评
- 下一篇: java -uf_Java如何快速修改J