Semaphore 簡單使用

文字摘抄於:https://yq.aliyun.com/articles/632589
Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。換句話說,鎖(Lock鎖或synchronized鎖)在任何時刻只允許一個任務訪問被加鎖的資源,而計數信號量允許n個任務同時訪問這個資源,還可以將信號量看作是向外分發使用資源的“許可證”,儘管內部沒有這種許可證對象。

“許可證”的數量是有限的,所以當執有“許可證”的線程數量與“許可證”數量相同時,就會阻止其他線程對共享資源的使用,如果某一個或多個線程使用完共享資源後,就會歸還“許可證”,此時Semaphore(信號量)就會將這些歸還的“許可證”再次分發給阻塞中的線程。通過這種方式就實現了控制線程併發數。

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

代碼

public static void main(String[] args) throws InterruptedException {

        // 同一時間,允許最大線程數量獲取
        final MySemaphore semaphore = new MySemaphore(1);

        for(int i = 0; i<2; i++ )
            new Thread(() -> {
                try {
                    // 獲取信號量
                    semaphore.acquire();
                    //boolean b = semaphore.tryAcquire(); 嘗試去拿,這個方法有入參
                    // semaphore.drainPermits(); // 獲取所有的許可證

                    TimeUnit.SECONDS.sleep(2);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    // 釋放
                    semaphore.release();
                }
            }).start();

        while(true){
            System.out.println("AP: " + semaphore.availablePermits()); // 當前可用的信號量
            System.out.println("QL: " + semaphore.getQueueLength()); // 阻塞的信號量

            semaphore.hasQueuedThreads(); // 是否有等待線程
            Collection<Thread> queuedThreads = semaphore.getQueuedThreads(); // 在等待的線程隊列

            TimeUnit.SECONDS.sleep(1);
        }

    }

    static class MySemaphore extends Semaphore{

        public MySemaphore(int permits) {
            super(permits);
        }

        public MySemaphore(int permits, boolean fair) {
            super(permits, fair);
        }

        @Override
        protected Collection<Thread> getQueuedThreads() {
            return super.getQueuedThreads();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章