Java並發工具類之並發數控制神器Semaphore


  Semaphore(信號量)使用來控制通知訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。

  我們可以這么理解Semaphore,比如一個廁所只有6個坑,同時只能滿足6個人上廁所(變態除外),其他人想蹲坑,只能排隊等待,如果有人從廁所出來,后面的一個人就可以進去。在這個例子中人就是線程,蹲坑表示線程在執行,離開表示線程執行完畢,而坑的數量就表示Semaphore的個數。

  一.Semaphore的應用場景

  Semaphore可以用於做流量控制,特別是公用資源有限的應用場景,比如數據庫連接。假如有一個需求,要讀取幾萬個文件的數據,因為都是IO密集型任務,我們可以啟動幾十個線程並發地讀取,但是如果讀到內存后,還需要存儲到數據庫中,而數據庫的連接數只有10個,這時我們必須控制只有10個線程同時獲取數據庫連接保存數據,否則會報錯無法獲取數據庫連接。這個時候,就可以使用Semaphore來做流量控制。簡單實現如下:

  

public class SemaphoreTest {

    private static final int THREAD_COUNT = 30;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);

    //只有10個數據庫鏈接,這里創建10個信號量
    private static Semaphore semaphore = new Semaphore(10);

    public static void main(String[] args){
        boolean shutDownThreadPool = false;

        for(int index = 0; index < THREAD_COUNT ;index++){
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        //獲取一個信號
                        semaphore.acquire();
                        //執行操作
                        System.out.println("wait for write data...");
                        Thread.sleep(1000);
                        //釋放信號
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            if(index == THREAD_COUNT-1){
                shutDownThreadPool = true;
            }
        }

        while(!shutDownThreadPool){
            threadPool.shutdown();
        }
    }

}

  上述代碼中雖然創建了30個線程,但是同時只能有是個線程在並發的執行。Semaphore的構造方法Semaphore(int permits)接受一個整型的數字,表示可用的許可證數量。Semaphore(10)表示允許10個線程獲取許可證,也就是最大並發數是10。Semaphore的用法也很簡單,首先線程使用Semaphore的acquire()方法獲取一個許可證,使用完之后調用release()方法歸還許可證。還可以用tryAcquire()方法嘗試獲取許可證。

  二.Semaphore的其他方法

  int availablePermits():返回當前可用的許可證數量

  int getQueueLength():獲取正在等待獲取許可證的線程數量

  boolean hasQueuedThreads():獲取是否還有等待獲取許可證的線程

  void reducePermits(int reduction):減少reduction個許可證


免責聲明!

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



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