java高併發(複習-7)信號量(Semaphore)

前言:信號量從概念上講,信號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再獲取該許可。每個 release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進行計數,並採取相應的行動。能併發控制訪問cpu線程的數目。實際就是可以允許多個線程併發訪問共享資源。

一,構造方法

第二個構造方法提供了是否公平

當設置爲false時,那麼這個類對線程獲取許可的順序做任何保證,也就是說可以在已經等待的線程前爲調用 acquire() 的線程分配一個許可,從邏輯上說,就是新線程將自己置於等待線程隊列的頭部。因爲內部實現也是基於AQS組件的。

當設置爲true時,信號量保證對於任何調用 acquire()方法的線程而言,都按照處理它們調用這些方法的順序(即先進先出;FIFO)來選擇線程、獲得許可。

二,常用的幾個方法

注意,acquire()方法和acquireUninteruptibly()雖然能使線程在獲得許可前被阻塞,但不能中斷響應(對於synchronized,一個線程在等待鎖,一般會有兩種情況,要麼線程獲得鎖繼續執行,要麼線程一直處於等待鎖的狀態,但是重入鎖會提供另外一種可能,在線程等待鎖的過程中,程序可以取消線程對鎖的請求)

簡單實例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    public static class SemapDemo implements Runnable{
        //創建許可數爲5 的
        final Semaphore semaphore = new Semaphore(5);
        @Override
        public void run() {
            try {
                semaphore.acquire();//獲得許可
                System.out.println(Thread.currentThread().getId() + "獲得許可!");
                Thread.sleep(1000);
                if (semaphore.hasQueuedThreads()){
                    System.out.println("線程池大約還有"+semaphore.getQueueLength()+"個線程在等待");
                }
                semaphore.release(5);//釋放5個許可
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(20);//創建線程池
        final SemapDemo semapDemo = new SemapDemo();
        for (int i = 0; i <20 ; i++) {
            pool.submit(semapDemo);//提交線程到線程池
        }
        pool.shutdown();
    }

}

從運行結果來看,設置5個許可,那麼在線程提交的時候首先會有5 個線程持有許可,同時提起來,其他的線程就處於等待的狀態。當釋放5個許可後就會又有五個線程獲得許可。

 

 

 

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