Semaphore的簡介及應用場景


Semaphore是一個計數信號量,常用於限制可以訪問某些資源(物理或邏輯的)線程數目。

常用函數: 
信號量的構造函數 
非公平:

public Semaphore(int permits);//permits就是允許同時運行的線程數目

公平(獲得鎖的順序與線程啟動順序有關):

public Semaphore(int permits,boolean fair);//permits就是允許同時運行的線程數目

創建一個信號量

Semaphore semaphore = new Semaphore(2);

從信號量中獲取一個許可

semaphore.acquire();

釋放一個許可(在釋放許可之前,必須先獲獲得許可。)

semaphore.release();

嘗試獲取一個許可,若獲取成功返回true,若獲取失敗返回false

semaphore.tryAcquire();

所有函數:

// 創建具有給定的許可數和非公平的公平設置的 Semaphore。
Semaphore(int permits)
// 創建具有給定的許可數和給定的公平設置的 Semaphore。
Semaphore(int permits, boolean fair)

// 從此信號量獲取一個許可,在提供一個許可前一直將線程阻塞,否則線程被中斷。
void acquire()
// 從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞,或者線程已被中斷。
void acquire(int permits)
// 從此信號量中獲取許可,在有可用的許可前將其阻塞。
void acquireUninterruptibly()
// 從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信號量中當前可用的許可數。
int availablePermits()
// 獲取並返回立即可用的所有許可。
int drainPermits()
// 返回一個 collection,包含可能等待獲取的線程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待獲取的線程的估計數目。
int getQueueLength()
// 查詢是否有線程正在等待獲取。
boolean hasQueuedThreads()
// 如果此信號量的公平設置為 true,則返回 true。
boolean isFair()
// 根據指定的縮減量減小可用許可的數目。
protected void reducePermits(int reduction)
// 釋放一個許可,將其返回給信號量。
void release()
// 釋放給定數目的許可,將其返回到信號量。
void release(int permits)
// 返回標識此信號量的字符串,以及信號量的狀態。
String toString()
// 僅在調用時此信號量存在一個可用許可,才從信號量獲取許可。
boolean tryAcquire()
// 僅在調用時此信號量中有給定數目的許可時,才從此信號量中獲取這些許可。
boolean tryAcquire(int permits)
// 如果在給定的等待時間內此信號量有可用的所有許可,並且當前線程未被中斷,則從此信號量獲取給定數目的許可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在給定的等待時間內,此信號量有可用的許可並且當前線程未被中斷,則從此信號量獲取一個許可。
boolean tryAcquire(long timeout, TimeUnit unit)

代碼實例: 
假設有10個人在銀行辦理業務,只有2個工作窗口,代碼實現邏輯如下

public class SemaphoreDemo {

    // 排隊總人數(請求總數)
    public static int clientTotal = 10;

    // 可同時受理業務的窗口數量(同時並發執行的線程數)
    public static int threadTotal = 2;


    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            final int count = i;
            executorService.execute(() -> {
                try {
                    semaphore.acquire(1);
                    resolve(count);
                    semaphore.release(2);
                } catch (Exception e) {
                    log.error("exception", e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
    }

    private static void resolve(int i) throws InterruptedException {
        log.info("服務號{},受理業務中。。。", i);
        Thread.sleep(2000);
    }
}

輸出結果:

21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號0,受理業務中。。。
21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號1,受理業務中。。。
21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號3,受理業務中。。。
21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號2,受理業務中。。。
21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號5,受理業務中。。。
21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號4,受理業務中。。。
21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號6,受理業務中。。。
21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號7,受理業務中。。。
21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號9,受理業務中。。。
21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號8,受理業務中。。。

從輸出結果可以看出,每隔兩秒,有兩個線程被執行

 

原文鏈接:https://blog.csdn.net/yuruixin_china/article/details/82084946

Semaphore是一個計數信號量,常用於限制可以訪問某些資源(物理或邏輯的)線程數目。
常用函數: 信號量的構造函數 非公平:
public Semaphore(int permits);//permits就是允許同時運行的線程數目1公平(獲得鎖的順序與線程啟動順序有關):
public Semaphore(int permits,boolean fair);//permits就是允許同時運行的線程數目1創建一個信號量
Semaphore semaphore = new Semaphore(2);1從信號量中獲取一個許可
semaphore.acquire();1釋放一個許可(在釋放許可之前,必須先獲獲得許可。)
semaphore.release();1嘗試獲取一個許可,若獲取成功返回true,若獲取失敗返回false
semaphore.tryAcquire();1所有函數:
// 創建具有給定的許可數和非公平的公平設置的 Semaphore。Semaphore(int permits)// 創建具有給定的許可數和給定的公平設置的 Semaphore。Semaphore(int permits, boolean fair)
// 從此信號量獲取一個許可,在提供一個許可前一直將線程阻塞,否則線程被中斷。void acquire()// 從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞,或者線程已被中斷。void acquire(int permits)// 從此信號量中獲取許可,在有可用的許可前將其阻塞。void acquireUninterruptibly()// 從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞。void acquireUninterruptibly(int permits)// 返回此信號量中當前可用的許可數。int availablePermits()// 獲取並返回立即可用的所有許可。int drainPermits()// 返回一個 collection,包含可能等待獲取的線程。protected Collection<Thread> getQueuedThreads()// 返回正在等待獲取的線程的估計數目。int getQueueLength()// 查詢是否有線程正在等待獲取。boolean hasQueuedThreads()// 如果此信號量的公平設置為 true,則返回 true。boolean isFair()// 根據指定的縮減量減小可用許可的數目。protected void reducePermits(int reduction)// 釋放一個許可,將其返回給信號量。void release()// 釋放給定數目的許可,將其返回到信號量。void release(int permits)// 返回標識此信號量的字符串,以及信號量的狀態。String toString()// 僅在調用時此信號量存在一個可用許可,才從信號量獲取許可。boolean tryAcquire()// 僅在調用時此信號量中有給定數目的許可時,才從此信號量中獲取這些許可。boolean tryAcquire(int permits)// 如果在給定的等待時間內此信號量有可用的所有許可,並且當前線程未被中斷,則從此信號量獲取給定數目的許可。boolean tryAcquire(int permits, long timeout, TimeUnit unit)// 如果在給定的等待時間內,此信號量有可用的許可並且當前線程未被中斷,則從此信號量獲取一個許可。boolean tryAcquire(long timeout, TimeUnit unit)1234567891011121314151617181920212223242526272829303132333435363738394041代碼實例: 假設有10個人在銀行辦理業務,只有2個工作窗口,代碼實現邏輯如下
package com..concurrency.yuxin.demo;
import lombok.extern.slf4j.Slf4j;import org.joda.time.DateTime;import org.joda.time.format.DateTimeFormat;import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;
@Slf4jpublic class SemaphoreDemo {
    // 排隊總人數(請求總數)    public static int clientTotal = 10;
    // 可同時受理業務的窗口數量(同時並發執行的線程數)    public static int threadTotal = 2;

    public static void main(String[] args) throws Exception {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i < clientTotal; i++) {            final int count = i;            executorService.execute(() -> {                try {                    semaphore.acquire(1);                    resolve(count);                    semaphore.release(2);                } catch (Exception e) {                    log.error("exception", e);                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();    }
    private static void resolve(int i) throws InterruptedException {        log.info("服務號{},受理業務中。。。", i);        Thread.sleep(2000);    }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849輸出結果:
21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號0,受理業務中。。。21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號1,受理業務中。。。21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號3,受理業務中。。。21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號2,受理業務中。。。21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號5,受理業務中。。。21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號4,受理業務中。。。21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號6,受理業務中。。。21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號7,受理業務中。。。21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號9,受理業務中。。。21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號8,受理業務中。。。12345678910從輸出結果可以看出,每隔兩秒,有兩個線程被執行--------------------- 版權聲明:本文為CSDN博主「yuruixin_china」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/yuruixin_china/article/details/82084946


免責聲明!

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



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