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