1. 程式人生 > >CountDownLatch、CyclicBarrier和Semaphore使用

CountDownLatch、CyclicBarrier和Semaphore使用

post i++ release 正在 多少 wait rup int args

  • CountDownLatch

CountDownLatch是用來線程計數的。等待一組線程全部執行完後再本線程繼續執行。如:A線程需要等待B、C和D(由初始化CountDownLatch參數覺得等待多少個線程)線程執行完後再執行。

主要的方法:

// 構造方法,count決定等待多少個線程
public CountDownLatch(int count)
// 等待線程完成數減1
public void countDown()
// 調用await本線程會掛起,當等待線程未完成數為0,即countDown調用次數等於構造方法參數值時會被喚醒
public void await()
public boolean await(long timeout, TimeUnit unit)

以下是CountDownLatch的用法:

public class CountDownLatchTest {
    public static void main(String[] args) {
        final CountDownLatch countDownLatch = new CountDownLatch(2);
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                try {
                    String name = Thread.currentThread().getName();
                    System.out.println("子線程" + name + "正在運行中......");
                    TimeUnit.SECONDS.sleep(5);
                    System.out.println("子線程" + name + "執行完畢");
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

        try {
            System.out.println("======等待兩個子線程執行完畢");
            // 只有子線程執行完畢個數等於CountDownLatch初始化個數才會繼續執行await後面代碼
            countDownLatch.await();
            System.out.println("兩個子線程都執行完畢!!!!!!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("主線程繼續執行中。。。。。。。。");
    }
}

結果:

子線程Thread-0正在運行中......
======等待兩個子線程執行完畢
子線程Thread-1正在運行中......
子線程Thread-1執行完畢
子線程Thread-0執行完畢
兩個子線程都執行完畢!!!!!!
主線程繼續執行中。。。。。。。。
  • CyclicBarrier

CyclicBarrier 設置一個障礙點,讓同組線程到達改點的線程等待本組未達到該點的線程,同組全部線程到達該點才越過障礙物釋放資源,讓其它組循環利用該對象。

主要方法:

// 構造方法設置同組線程數
public CyclicBarrier(int parties)
// 構造方法設置同組線程數;全部達到障礙物時執行barrierAction函數
public CyclicBarrier(int parties, Runnable barrierAction)
// 某個線程調用await時掛起,需要等同組所有線程到達才能喚醒
public int await() throws InterruptedException, BrokenBarrierException

以下是 CyclicBarrier 的用法:

/**
 * Created on 18/3/15 14:40.
 *
 * @author wolf
 */
public class CyclicBarrierTest {
    public static void main(String[] args) {
        int n = 3;
        CyclicBarrier barrier = new CyclicBarrier(n);
        for (int i = 0; i < 3; i++) {
            new Worker(barrier).start();
        }

        try {
            TimeUnit.SECONDS.sleep(6);
            System.out.println("--------討厭的循環利用分割線------------");
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (int i = 0; i < n; i++) {
            new Worker(barrier).start();
        }
    }

    static class Worker extends Thread {
        private CyclicBarrier barrier;
        public Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        @Override
        public void run() {
            long startTime = System.currentTimeMillis();
            String name = Thread.currentThread().getName();
            System.out.println("線程 " + name + " 正在執行任務.......");
            try {
                int time = RandomUtils.nextInt(1, 5);
                TimeUnit.SECONDS.sleep(time);
                System.out.println("線程 " + name + " 執行任務完畢!!!用時:" + time);
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("線程 " + name + " 全部耗時:"+(System.currentTimeMillis()-startTime));
        }
    }
}
  • Semaphore

Semaphore 通過名字我們就知道這個計算信號量,也就是控制獲取資源的許可證。

主要的方法:

// 構造方法設置可用資源的數量,即許可證的數量
public Semaphore(int permits)
// 構造方法設置可用資源的數量,即許可證的數量,fair 是否公平獲得許可證,默認是先來後到公平的
public Semaphore(int permits, boolean fair)
// 同步獲取許可證,
public void acquire() throws InterruptedException
// 嘗試獲取許可證,結果直接返回
public boolean tryAcquire()
// 嘗試獲取許可證,結果等待時間超時直接返回
public boolean tryAcquire(long timeout, TimeUnit unit)
// 釋放許可證,可給其它等待線程使用
public void release()

以下是 Semaphore 用法:

public class SemaphoreTest {
    public static void main(String[] args) {
        int no = 5;
        Semaphore semaphore = new Semaphore(2);
        for (int i = 0; i < no; i++) {
            new Worker(i, semaphore).start();
        }
    }
    static class Worker extends Thread {
        private int no;
        private Semaphore semaphore;
        public Worker(int no, Semaphore semaphore) {
            this.no = no;
            this.semaphore = semaphore;
        }
        @Override
        public void run() {
            try {
                long startTime = System.currentTimeMillis();
                semaphore.acquire();
                System.out.println("worker " + this.no + " 獲取許可證,開始工作....");
                int time = RandomUtils.nextInt(1, 5);
                TimeUnit.SECONDS.sleep(time);
                semaphore.release();
                System.out.println("worker " + this.no + " 完成工作,釋放許可證!耗時:" + (System.currentTimeMillis() - startTime));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

CountDownLatch、CyclicBarrier和Semaphore使用