1. 程式人生 > >java並發之同步輔助類CountDownLatch

java並發之同步輔助類CountDownLatch

java 同步 多線程

CountDownLatch

含義:

CountDownLatch可以理解為一個計數器在初始化時設置初始值,當一個線程需要等待某些操作先完成時,需要調用await()方法。這個方法讓線程進入休眠狀態直到等待的所有線程都執行完成。每調用一次countDown()方法內部計數器減1,直到計數器為0時喚醒。這個可以理解為特殊的CyclicBarrier。線程同步點比較特殊,為內部計數器值為0時開始。

方法:
核心方法兩個:countDown()和await()
countDown():使CountDownLatch維護的內部計數器減1,每個被等待的線程完成的時候調用
await():線程在執行到CountDownLatch的時候會將此線程置於休眠

例子
開會的例子:會議室裏等與會人員到齊了會議才能開始。

import java.util.concurrent.CountDownLatch;

public class VideoConference implements Runnable {
private final CountDownLatch controller;

public VideoConference(int number) {
    controller = new CountDownLatch(number);
}

public void arrive(String name) {
    System.out.printf("%s has arrived.\n", name);

    controller.countDown();// 調用countDown()方法,使內部計數器減1
    System.out.printf("VideoConference: Waiting for %d participants.\n", controller.getCount());
}

@Override
public void run() {
    System.out.printf("VideoConference: Initialization: %d participants.\n", controller.getCount());
    try {

        controller.await();// 等待,直到CoutDownLatch計數器為0

        System.out.printf("VideoConference: All the participants have come\n");
        System.out.printf("VideoConference: Let‘s start...\n");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

參加會議人員類

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PrintQueue {
//信號量
private Semaphore semaphore;

//是否空閑打印機
private boolean freePrinters[];

private Lock lockPrinters;

public PrintQueue(){
    //初始化三個信號
    semaphore=new Semaphore(3);
    //三臺空閑打印機
    freePrinters=new boolean[3];
    for (int i=0; i<3; i++){
        freePrinters[i]=true;
    }
    lockPrinters=new ReentrantLock();
}

public void printJob (Object document){
    try {
        //獲取信號量
        semaphore.acquire();

        int assignedPrinter=getPrinter();

        Long duration=(long)(Math.random()*10);
        System.out.printf("%s: PrintQueue: Printing a Job in Printer %d during %d seconds\n",Thread.currentThread().getName(),assignedPrinter,duration);
        TimeUnit.SECONDS.sleep(duration);

        freePrinters[assignedPrinter]=true;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        // Free the semaphore
        semaphore.release();            
    }
}
private int getPrinter() {
    int ret=-1;

    try {
        lockPrinters.lock();
        for (int i=0; i<freePrinters.length; i++) {
            if (freePrinters[i]){
                ret=i;
                freePrinters[i]=false;
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        lockPrinters.unlock();
    }
    return ret;
}

}

測試類:

public class CountDownLatchMain {

public static void main(String[] args) {
    VideoConference conference = new VideoConference(10);
    Thread threadConference = new Thread(conference);
    threadConference.start();// 開啟await()方法,在內部計數器為0之前線程處於等待狀態
    for (int i = 0; i < 10; i++) {
        Participant p = new Participant(conference, "Participant " + i);
        Thread t = new Thread(p);
        t.start();
    }
}

}

海量視頻
技術分享圖片

java並發之同步輔助類CountDownLatch