1. 程式人生 > >多執行緒(十二): 訊號量Semaphore

多執行緒(十二): 訊號量Semaphore

應用場景:多個執行緒使用數量有限的資源。

Semaphore是一種基於計數的訊號量。它可以設定一個閥值,基於此,多個執行緒競爭獲取許可訊號,做自己的申請後歸還,超過閥值後,執行緒申請許可訊號將會被阻塞。
Semaphore可以用來構建一些物件池,資源池之類的,比如資料庫連線池,我們也可以建立計數為1的Semaphore,將其作為一種類似互斥鎖的機制,這也叫二元訊號量,表示兩種互斥狀態。

public class Semaphore implements java.io.Serializable {
    // 最多支援N個資源訪問
    public Semaphore(int
permits); // 獲取可用的資源, // 如果可用, 訊號量內部的資源個數減掉1, // 如果沒有可用資源執行緒會阻塞在該方法中,不能結束該方法,不能返回,直到有可用的資源為止 public void acquire() throws InterruptedException; // 當前可用的資源個數, permits - availablePermits() = 正在使用的資源個數 public int availablePermits(); // 釋放資源,釋放後訊號量內部的資源個數會增加1 // 如果有被阻塞的執行緒,釋放後會喚醒一個執行緒去獲取資源
// acquire() 和 release()要成對使用,一般release()放在finally程式碼塊中 public void release(); }

這裡寫圖片描述

public class SemaphoreTest {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 10; i++) {
            new Thread(new MyRunnable(semaphore), "第"
+ i + "個人").start(); } } } class MyRunnable implements Runnable { private Semaphore semaphore; public MyRunnable(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { String name = Thread.currentThread().getName(); int availablePermits = semaphore.availablePermits(); if (availablePermits > 0) { System.out.println(name + "無人,可用"); } else { System.out.println(name + "有人,請排隊。。。\t?"); } try { // 如果沒有拿到資源將一直等待,直到有人釋放,拿到資源 semaphore.acquire(); System.out.println(name + "輪到我了"); // 模擬使用時間 Thread.sleep(1000); System.out.println(name + "使用完畢\t?"); } catch (InterruptedException e) { } finally { // 使用完釋放資源 semaphore.release(); } } }

這裡寫圖片描述