1. 程式人生 > >Semaphore的簡介及應用場景

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,則返回 trueboolean 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個工作視窗,程式碼實現邏輯如下

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;

@Slf4j
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,受理業務中。。。

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