最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的Semaphore(信號量)全面解析

 更新時間:2025年08月20日 09:28:58   作者:MOONNIFE  
信號量(Semaphore)是Java多線程兵法中的一種JDK內置同步器,通過它可以實現(xiàn)多線程對公共資源的并發(fā)訪問控制,這篇文章主要介紹了Java中Semaphore(信號量)的相關資料,需要的朋友可以參考下

前言

Semaphore 是 Java 并發(fā)包(java.util.concurrent)中的核心同步工具類,用于??控制對共享資源的并發(fā)訪問數(shù)量??,通過“許可證”機制實現(xiàn)資源限流。下面從多個維度全面解析其設計原理和應用實踐。

一、基本概念與核心原理??

1. 核心模型??

  • ??信號量模型??:
    Semaphore 維護一個??許可證計數(shù)器??(permits),通過原子操作控制資源訪問:
    • ??acquire()??(P操作):申請許可證,計數(shù)器減 1;若無可用許可證,線程阻塞。
    • ??release()??(V操作):釋放許可證,計數(shù)器加 1,喚醒阻塞線程。
  • ??公平性??:
    • ??非公平模式(默認)??:允許線程插隊獲取許可,吞吐量高但可能引發(fā)線程饑餓。
    • ??公平模式??:按 FIFO 順序分配許可,避免饑餓但性能較低。

??2. 底層實現(xiàn)??

基于 ??AQS(AbstractQueuedSynchronizer)?? 的共享鎖模式實現(xiàn):

  • ??狀態(tài)變量??:AQS 的 state 字段存儲當前可用許可證數(shù)量。
  • ??關鍵源碼邏輯??:
    // 非公平模式嘗試獲取許可
    final int nonfairTryAcquireShared(int acquires) {
        for (;;) {
            int available = getState();
            int remaining = available - acquires;
            if (remaining < 0 || compareAndSetState(available, remaining)) 
                return remaining; // 負數(shù)表示獲取失敗
        }
    }
    // 釋放許可
    protected final boolean tryReleaseShared(int releases) {
        for (;;) {
            int current = getState();
            int next = current + releases;
            if (compareAndSetState(current, next)) 
                return true; // 喚醒阻塞線程
        }
    }

?二、使用方式與代碼示例??

1. 基礎用法??

import java.util.concurrent.Semaphore;

public class PrinterService {
    private final Semaphore semaphore = new Semaphore(3); // 初始化3個許可證

    public void printDocument(String docName) throws InterruptedException {
        semaphore.acquire(); // 獲取許可(阻塞直到可用)
        try {
            System.out.println("Printing: " + docName);
            Thread.sleep(1000); // 模擬打印耗時
        } finally {
            semaphore.release(); // 必須釋放許可!
        }
    }
}

??2. 高級方法:超時與批量操作??

// 嘗試獲取許可(超時控制)
if (semaphore.tryAcquire(2, 500, TimeUnit.MILLISECONDS)) {
    try {
        // 執(zhí)行任務
    } finally {
        semaphore.release(2); // 釋放多個許可
    }
} else {
    System.out.println("獲取許可超時!");
}

3. 多線程場景示例??

public static void main(String[] args) {
    PrinterService service = new PrinterService();
    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            try {
                service.printDocument("Doc-" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

??輸出效果??:

Printing: Doc-Thread-0  
Printing: Doc-Thread-1  
Printing: Doc-Thread-2  // 僅3個線程并發(fā)執(zhí)行  
Thread-2 釋放許可 → Thread-3 開始打印  
...  

三、優(yōu)缺點分析??

??維度????優(yōu)點????缺點??
??性能??讀操作無鎖,高并發(fā)場景吞吐量高(尤其非公平模式)。寫操作需復制數(shù)組,頻繁修改時性能差(時間復雜度 O(n))。
??資源控制??精準限制并發(fā)量,避免資源過載。許可證泄漏(未釋放)會導致資源逐漸耗盡。
??一致性??弱一致性模型,迭代器安全(基于快照)。無法實時感知最新修改,迭代期間數(shù)據(jù)可能過期。
??靈活性??支持動態(tài)調整許可證數(shù)量、超時控制、批量操作。復雜同步需求需結合其他工具(如 CountDownLatch)。

四、適用場景??

1. 資源池管理??

  • ??數(shù)據(jù)庫連接池??:限制同時使用的連接數(shù),防止連接耗盡。
    public class ConnectionPool {
        private final Semaphore semaphore = new Semaphore(MAX_CONNECTIONS);
        private final BlockingQueue<Connection> pool = new LinkedBlockingQueue<>();
    
        public Connection borrow() throws InterruptedException {
            semaphore.acquire();
            return pool.take();
        }
        public void release(Connection conn) {
            pool.offer(conn);
            semaphore.release();
        }
    }

2. 流量控制??

  • ??API 限流??:限制每秒請求數(shù),防止服務雪崩。
    public class RateLimiter {
        private final Semaphore semaphore = new Semaphore(100); // 每秒100個請求
        private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
        public RateLimiter() {
            scheduler.scheduleAtFixedRate(() -> 
                semaphore.release(semaphore.drainPermits()), 1, 1, TimeUnit.SECONDS);
        }
        public void callAPI(Runnable task) throws InterruptedException {
            semaphore.acquire();
            task.run();
        }
    }

3. 物理資源共享??

  • ??打印機/文件系統(tǒng)??:控制多線程訪問共享硬件資源。
    semaphore.acquire();
    try {
        Files.write(Paths.get("log.txt"), data, StandardOpenOption.APPEND);
    } finally {
        semaphore.release();
    }

?五、注意事項與最佳實踐??

  • ??避免許可證泄漏??:
    • 確保 release() 在 finally 塊中調用,防止異常導致許可未釋放。
  • ??合理選擇公平性??:
    • 高吞吐場景用非公平模式,嚴格順序需求用公平模式。
  • ??控制許可證數(shù)量??:
    • 過多導致資源浪費,過少引發(fā)線程饑餓(通過監(jiān)控 availablePermits() 動態(tài)調整)。
  • ??避免嵌套死鎖??:
    • 若需多信號量,按固定順序獲?。ㄈ缦?A 后 B),防止交叉等待。

總結??

Semaphore 是解決??資源并發(fā)控制??的利器,尤其適合??讀多寫少、資源池限流、API控頻??等場景。其基于 AQS 的實現(xiàn)兼顧了靈活性與性能,但需注意許可證管理的原子性和釋放的可靠性。在高并發(fā)系統(tǒng)中,合理使用 Semaphore 能有效提升系統(tǒng)穩(wěn)定性與資源利用率??。

到此這篇關于Java中的Semaphore(信號量)的文章就介紹到這了,更多相關Java中Semaphore內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Eclipse運行android項目報錯Unable to build: the file dx.jar was not loaded from the SDK folder的解決辦法

    Eclipse運行android項目報錯Unable to build: the file dx.jar was not

    今天小編就為大家分享一篇關于Eclipse運行android項目報錯Unable to build: the file dx.jar was not loaded from the SDK folder的解決辦法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Spring Boot定時器創(chuàng)建及使用解析

    Spring Boot定時器創(chuàng)建及使用解析

    這篇文章主要介紹了Spring Boot定時器創(chuàng)建及使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Java SPI 機制知識點總結

    Java SPI 機制知識點總結

    在本篇文章里小編給大家整理的是一篇關于Java SPI 機制知識點總結內容,需要的朋友們可以參考下。
    2020-02-02
  • Springboot使用jxls實現(xiàn)同sheet多個列表展示

    Springboot使用jxls實現(xiàn)同sheet多個列表展示

    這篇文章主要介紹了Springboot使用jxls實現(xiàn)同sheet多個列表展示,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 一文快速掌握Java中的搜索算法和排序算法

    一文快速掌握Java中的搜索算法和排序算法

    這篇文章主要為大家詳細介紹了Java中常用的搜索算法和排序算法的實現(xiàn),例如二分查找、冒泡排序、選擇排序等,文中的示例代碼講解詳細,希望對大家有所幫助
    2023-04-04
  • Java中使用標簽(label)來控制循環(huán)的執(zhí)行流程

    Java中使用標簽(label)來控制循環(huán)的執(zhí)行流程

    java 和 label 兩個完全不相干的詞,今天我把他們連接在一起了,試想一個問題,雙循環(huán)在不使用 return 的情況下,如何停止外循環(huán)?所以本文給大家介紹了Java中使用標簽(label)來控制循環(huán)的執(zhí)行流程,需要的朋友可以參考下
    2024-06-06
  • Java之while與do-while循環(huán)的用法詳解

    Java之while與do-while循環(huán)的用法詳解

    在上一篇文章中,給大家講解了循環(huán)的概念,并重點給大家講解了for循環(huán)的使用。但在Java中,除了for循環(huán)之外,還有while、do-while、foreach等循環(huán)形式。這篇文章給大家講解while循環(huán)的使用
    2023-05-05
  • idea中maven項目模塊變成灰色原因及解決方案

    idea中maven項目模塊變成灰色原因及解決方案

    這篇文章主要介紹了idea中maven項目模塊變成灰色原因及解決方案,文中通過圖文結合的方式給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Java之Zookeeper注冊中心原理剖析

    Java之Zookeeper注冊中心原理剖析

    這篇文章主要介紹了Java之Zookeeper注冊中心原理剖析,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • Java基礎教程之final關鍵字淺析

    Java基礎教程之final關鍵字淺析

    這篇文章主要給大家介紹了關于Java基礎教程之final關鍵字的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-06-06

最新評論

青浦区| 陆川县| 同仁县| 文安县| 扶绥县| 武定县| 固阳县| 六安市| 九江市| 尤溪县| 资源县| 民权县| 怀远县| 石渠县| 义马市| 长泰县| 东兰县| 鹤峰县| 石家庄市| 长泰县| 锡林浩特市| 铅山县| 泰兴市| 河曲县| 云安县| 巴马| 临沭县| 长阳| 富顺县| 西乌珠穆沁旗| 含山县| 监利县| 新邵县| 大兴区| 河东区| 开化县| 夏邑县| 周口市| 永嘉县| 乌兰浩特市| 黄石市|