1. 程式人生 > >Java併發程式設計札記-(四)JUC鎖-10Semaphore簡介

Java併發程式設計札記-(四)JUC鎖-10Semaphore簡介

一般的鎖在任意時刻只允許一個執行緒訪問一項資源,而計數訊號量允許n個任務同時訪問一項資源。我們可以將訊號量看做一個許可集,可以向執行緒分發使用資源的許可證。獲得資源前,執行緒呼叫acquire()從許可集中獲取許可。該執行緒結束後,通過release()將許可還給許可集。

函式列表

//構造方法摘要
Semaphore(int permits) 
          //建立具有給定的許可數和非公平的公平設定的 Semaphore。
Semaphore(int permits, boolean fair) 
          //建立具有給定的許可數和給定的公平設定的 Semaphore。  
//方法摘要
void acquire() //從此訊號量獲取一個許可,在提供一個許可前一直將執行緒阻塞,否則執行緒被中斷。 void acquire(int permits) //從此訊號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞,或者執行緒已被中斷。 void acquireUninterruptibly() //從此訊號量中獲取許可,在有可用的許可前將其阻塞。 void acquireUninterruptibly(int permits) //從此訊號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞。
int availablePermits() //返回此訊號量中當前可用的許可數。 int drainPermits() //獲取並返回立即可用的所有許可。 protected Collection<Thread> getQueuedThreads() //返回一個 collection,包含可能等待獲取的執行緒。 int getQueueLength() //返回正在等待獲取的執行緒的估計數目。 boolean hasQueuedThreads() //查詢是否有執行緒正在等待獲取。 boolean
isFair() //如果此訊號量的公平設定為 true,則返回 trueprotected void reducePermits(int reduction) //根據指定的縮減量減小可用許可的數目。 void release() //釋放一個許可,將其返回給訊號量。 void release(int permits) //釋放給定數目的許可,將其返回到訊號量。 String toString() //返回標識此訊號量的字串,以及訊號量的狀態。 boolean tryAcquire() //僅在呼叫時此訊號量存在一個可用許可,才從訊號量獲取許可。 boolean tryAcquire(int permits) //僅在呼叫時此訊號量中有給定數目的許可時,才從此訊號量中獲取這些許可。 boolean tryAcquire(int permits, long timeout, TimeUnit unit) //如果在給定的等待時間內此訊號量有可用的所有許可,並且當前執行緒未被中斷,則從此訊號量獲取給定數目的許可。 boolean tryAcquire(long timeout, TimeUnit unit) //如果在給定的等待時間內,此訊號量有可用的許可並且當前執行緒未被中斷,則從此訊號量獲取一個許可。

此類的構造方法可選地接受一個公平引數fair。當fair設定為false時,此類不對執行緒獲取許可的順序做任何保證,也就是說可以在已經等待的執行緒前為呼叫acquire() 的執行緒分配一個許可。當公平設定為true時,訊號量保證對於任何呼叫acquire()的執行緒而言,都按照FIFO的規則來選擇執行緒、獲得許可。注意,FIFO排序必然應用到這些方法內的指定內部執行點。所以,可能某個執行緒先於另一個執行緒呼叫了 acquire(),但是卻在該執行緒之後到達排序點,並且從方法返回時也類似。還要注意,非同步的tryAcquire()方法不使用公平設定,而是使用任意可用的許可。

通常,應該將用於控制資源訪問的訊號量初始化為公平的,以確保所有執行緒都可訪問資源。為其他的種類的同步控制使用訊號量時,非公平排序的吞吐量優勢通常要比公平考慮更為重要。

例1:訊號量的簡單使用

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        // 建立許可數為3和非公平的公平設定的 Semaphore。
        final Semaphore semp = new Semaphore(3);
        // 模擬10個客戶端訪問
        for (int index = 0; index < 10; index++) {
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        // 從此訊號量獲取一個許可
                        semp.acquire();
                        System.out.println(Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                    } finally {
                        // 釋放訊號量。如果沒有這條語句,則在控制檯只能列印5條記錄,之後執行緒一直阻塞
                        semp.release();
                    }
                }
            };
            exec.execute(run);
        }
        exec.shutdown();
    }
}

原始碼
待補充

本文就講到這裡,想了解Java併發程式設計更多內容請參考: