併發流程工具Semaphore的使用

一個計數信號量。 在概念上,信號量維持一組許可證。 如果有必要,每個acquire()都會阻塞,直到許可證可用,然後才能使用它。 每個release()添加許可證,潛在地釋放阻塞的線程。 記得以前校招,一個公司對應很多面試的學生,因爲人數太多每次至多面試5個人,其他人只能等待,除非有人出來,等待的人才有機會進去,一般是排隊公平進去,但是大家爲了找工作都是搶着進去面試,大概是這麼個意思。等待就是acquire(),有人出來就是release(),Semaphore底層使用AQS實現

案例分析

public class SemaphoreDemo {
    //添加3個許可證,採取公平策略,默認是分公平的
    static Semaphore semaphore = new Semaphore(3, true);

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(50);
        for (int i = 0; i < 10; i++) {
            service.submit(new Task());
        }
        service.shutdown();
    }

    static class Task implements Runnable {

        @Override
        public void run() {
            try {
                //每個線程需要3個許可證才能進來,如果沒有3個就阻塞,直到有滿足的許可證可用
                semaphore.acquire(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了許可證");
//            try {
//                Thread.sleep(2000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            System.out.println(Thread.currentThread().getName() + "釋放了許可證");
            //釋放三個許可證
            semaphore.release(3);
        }
    }
}

在這裏插入圖片描述
如果 semaphore.acquire(3);改爲 semaphore.acquire(4);那麼所有線程都會阻塞,因爲總共就只有三個許可證,或者 semaphore.release(3);改爲 semaphore.release(2);那麼第從二個線程開始所有線程都會阻塞,因爲執行需要3個許可證,但是第一個執行的線程只釋放了2個許可證

總之.release()操作happen-before acquire()操作,即釋放操作在獲取操作之前,釋放對獲取可見

此類共有兩個構造方法,兩個參數的構造可以選擇公平策略,默認是非公平的。
.release()與acquire()默認參數是1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章