倒計時門閂就像一個帶計數開關的門,只有在門前等待的線程數量達到一定的數量時,門閂纔會打開,線程纔可以繼續執行。
實現類:
CountDownLatch,該類從Object繼承而來,可以通過一個給定的值進行初始化,通常在同步狀態中保存的是當前的計數值,線程的調用await()方法等待,方法countDown()會導致計數值遞減,當計數值爲零時,所有在倒計時門閂範圍內等
待線程的阻塞狀態將解除。
構造方法 如下:
CountDownLatch(int count)
其中,count爲初始計數,必須爲正數,否則將拋出IllegalArgumentExceptio異常。
倒計時門閂和同步障柵的不同點:
1) 不是所有的線程都需要等待門閂的打開;
2)門閂可以由外部的事件打開;
3)倒計時門閂是一次性的,一旦計數器爲零,就不再使用它。
demo 示例:
給一個數組的每一個元素加1。
//線程工作類
public class Worker extends Thread{
int [] array;
int from;
int to;
CountDownLatch cdl;
public Worker( int [] array,int from,int to,CountDownLatch cdl ){
this.array = array;
this.from = from;
this.to = to;
this.cdl = cdl;
}
public void run(){
for(int i=from;i<to;i++){
array[i]++;
}
cdl.countDown();
try{
cdl.await();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//啓動類
public class Index{
public static void main(String[] args){
int N = 100000;
int [] datum = new int [N];
int [] copy = new int[N];
for(int i=0;i<N;i++){
datum[i]=(int)(Math.random()*10);
copy[i] = datum[i];
}
int nthread = Runtime.getRuntime().availableProcessors();
int segment = N/nthread;
//線程數組
int [] range = new int[nthread+1];
for(int i=0;i<=nthread;i++){
range[i] = segment*i;
if(range[i]>N){
range[i] = N;
}
}
System.out.println("將數據劃分爲:");
for(int i=0;i<nthread;i++){
System.out.println(""+range[i] + "" + range[i+1]);
}
CountDownLatch cdl = new CountDownLatch(nthread);
Thread [] threads = new Thread[nthread];
for(int i=0;i<nthread;i++){
threads[i] = new Worker(datum,range[i],range[i+1],cdl);
threads[i].start();
}
try{
cdl.await();
}catch(InterruptedException e){
e.printStackTrace();
}
boolean pass = true;
for(int i=0;i<N;i++){
if(datum[i]!=copy[i]+1){
pass = false;
break;
}
}
if(pass){
System.out.println("結果正確!!");
}else{
System.out.println("結果錯誤,請仔細檢查代碼邏輯!");
}
}
}
運行結果:
將數據劃分爲:
開始的下標:0結束的下標12500
開始的下標:12500結束的下標25000
開始的下標:25000結束的下標37500
開始的下標:37500結束的下標50000
開始的下標:50000結束的下標62500
開始的下標:62500結束的下標75000
開始的下標:75000結束的下標87500
開始的下標:87500結束的下標100000
結果正確!!