CountDownLatch類 多線程之倒計時門閂

    倒計時門閂就像一個帶計數開關的門,只有在門前等待的線程數量達到一定的數量時,門閂纔會打開,線程纔可以繼續執行。
    實現類:
    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
結果正確!!

 

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