背景:最近做測(cè)試需要準(zhǔn)備大量的數(shù)據(jù),用單線程去連續(xù)調(diào)幾個(gè)接口耗時(shí)N秒,而數(shù)據(jù)量大這個(gè)時(shí)間消耗就成倍數(shù)增長(zhǎng),單線程效率太低,決定用多線程跑數(shù)據(jù)。
使用多線程,首先實(shí)現(xiàn)一個(gè)線程,再開辟一個(gè)線程池,循環(huán)調(diào)用。但是線程什么時(shí)候結(jié)束是個(gè)問(wèn)題,這里使用到了CountDownLatch。
Latch:英[l?t?], 門閂。
CountDownLatch 是一個(gè)同步工具類,它允許一個(gè)或多個(gè)線程一直等待,直到其他線程的操作執(zhí)行完成后再執(zhí)行。
CountDownLatch是通過(guò)一個(gè)計(jì)數(shù)器來(lái)實(shí)現(xiàn)的,計(jì)數(shù)器的初始值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后,計(jì)數(shù)器的值就會(huì)減1。當(dāng)計(jì)數(shù)器值達(dá)到0時(shí),表示所有的線程已經(jīng)完成了任務(wù),然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)了。
CountDownLatch的偽代碼如下所示:
1. //Main thread start
2. //Create CountDownLatch for N threads
3. //Create and start N threads
4. //Main thread wait on latch
5. //N threads completes there tasks are returns
6. //Main thread resume execution
CountDownLatch如何使用?
CountDownLatch.java類中定義的構(gòu)造函數(shù):
1.?//Constructs a CountDownLatch initialized with the given count.
2. public void CountDownLatch(int count) {...}
構(gòu)造器中的計(jì)數(shù)值實(shí)際上就是閉鎖需要等待的線程數(shù)量。這個(gè)值只能被設(shè)置一次,且不能被修改。
主線程必須在啟動(dòng)其他線程后立即調(diào)用CountDownLatch.await()方法。這樣主線程的操作就會(huì)在這個(gè)方法上阻塞,直到其他線程完成各自的任務(wù)。
其他N個(gè)線程必須引用閉鎖對(duì)象,因?yàn)樗麄冃枰ㄖ狢ountDownLatch對(duì)象,他們已經(jīng)完成了各自的任務(wù)。這種通知通過(guò)CountDownLatch.countDown()方法來(lái)完成;每一次調(diào)用這個(gè)方法,在構(gòu)造函數(shù)中初始化的count值就減1.所以當(dāng)所有N個(gè)線程都調(diào)用了這個(gè)方法,count=0,主線程就能通過(guò)await()方法,恢復(fù)執(zhí)行自己的任務(wù)。
代碼Demo:
public void bizDealCode(){
Long startTime = System.currentTimeMillis();
intsize =10000;
ExecutorService threadPool = Executors.newFixedThreadPool(15);
CountDownLatch countDownLatch =newCountDownLatch(size);
for(intj =0; j < size; ++j) {
threadPool.submit(newMakeOrderThread(countDownLatch));
}
System.out.println("finished submit");
try{
countDownLatch.await();
}catch(Exception e) {
}
System.out.println("finished process");
threadPool.shutdown();
System.out.println("costTime is "+ (System.currentTimeMillis() - startTime) +"ms");
}
static classMakeOrderThreadextendsThread {
privateCountDownLatchcountDownLatch;
publicMakeOrderThread(CountDownLatch countDownLatch) {
this.countDownLatch= countDownLatch;
}
@Override
public voidrun() {
try{
bizCode();
}catch(Exception e) {
}finally{
countDownLatch.countDown();
}
}
}
}