Java並發編程工具類 CountDownLatch CyclicBarrier Semaphore使用Demo


Java並發編程工具類 CountDownLatch CyclicBarrier Semaphore使用Demo

CountDownLatch

countDownLatch這個類使一個線程等待其他線程各自執行完畢后再執行。

是通過一個計數器來實現的,計數器的初始值是線程的數量。每當一個線程執行完畢后,計數器的值就-1,當計數器的值為0時,表示所有線程都執行完畢,然后在閉鎖上等待的線程就可以恢復工作了。

CountDownLatch中的方法

//調用await()方法的線程會被掛起,它會等待直到count值為0才繼續執行
public void await() throws InterruptedException { };   
//和await()類似,只不過等待一定的時間后count值還沒變為0的話就會繼續執行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
//將count值減1
public void countDown() { };  

CountDownLatchDemo

條件改為i<20時,並不會輸出“完結撒花”,因為latch還沒有減到0

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args)  {
        CountDownLatch latch = new CountDownLatch(20);
        //條件改為i<20時,並不會輸出“完結撒花”,因為latch還沒有減到0
        for (int i = 0; i < 20; i++) {
            int index=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    latch.countDown();
                    System.out.println(index);
                }
            }).start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("完結撒花");
    }
}

CyclicBarrier

CyclicBarrier可以使一定數量的線程反復地在柵欄位置處匯集。當線程到達柵欄位置時將調用await方法,這個方法將阻塞直到所有線程都到達柵欄位置。如果所有線程都到達柵欄位置,那么柵欄將打開,此時所有的線程都將被釋放,而柵欄將被重置以便下次使用。

  • CountDownLatch 是一次性的,CyclicBarrier 是可循環利用的

構造方法

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)
  • parties 是參與線程的個數
  • 第二個構造方法有一個 Runnable 參數,這個參數的意思是最后一個到達線程要做的任務

方法

public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
  • 線程調用 await() 表示自己已經到達柵欄
  • BrokenBarrierException 表示柵欄已經被破壞,破壞的原因可能是其中一個線程 await() 時被中斷或者超時

Demo

  • 初始化線程1,線程1睡眠3秒
  • 剩余九個線程到達barrier,但是並不會又輸出
  • 三秒后線程1到達,9個線程開始輸出
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(10);
        //初始化線程1,線程1睡眠3秒,等待剩余九個線程到達barrier
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.currentThread().sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //九個線程先到達barrier
        for (int i = 0; i < 9; i++) {
            int index=i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println(index);
                }
            }).start();
        }
    }
}
//Output,輸出是隨機的
/*
        0
        6
        2
        1
        8
        7
        4
        3
        5*/

Semaphore

Semaphore也是一個線程同步的輔助類,可以維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore可以控制同時訪問資源的線程個數,例如,實現一個文件允許的並發訪問數。

常用方法

  void acquire():從此信號量獲取一個許可,在提供一個許可前一直將線程阻塞,否則線程被中斷。

  void release():釋放一個許可,將其返回給信號量。

  int availablePermits():返回此信號量中當前可用的許可數。

  boolean hasQueuedThreads():查詢是否有線程正在等待獲取。

Demo

  • 六個人競爭三個辦事窗口,每個辦事窗口只能容納三個人,輸出如下
package ConcurrentApi;

import java.util.concurrent.Semaphore;
//Output
/*
    線程0等到了辦事窗口空閑
            辦事窗口剩余量2
    線程1等到了辦事窗口空閑
            辦事窗口剩余量1
    線程2等到了辦事窗口空閑
            辦事窗口剩余量0
    線程3等到了辦事窗口空閑
            辦事窗口剩余量0
    線程4等到了辦事窗口空閑
            辦事窗口剩余量0
    線程5等到了辦事窗口空閑
            辦事窗口剩余量0*/
public class SemaphoreDemo {
    public static void main(String[] args) {
        //初始化3 三個辦事窗口
        Semaphore semaphore = new Semaphore(3);
        for (int i = 0; i < 6; i++) {
            int index = i;
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        System.out.println("線程"+index+"等到了辦事窗口空閑");
                        System.out.println("辦事窗口剩余量"+semaphore.availablePermits());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.currentThread().sleep(4000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    semaphore.release();
                }
            }).start();
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM