寫在前面:
在前面兩篇博客中,介紹了CountDownLatch、CyclicBarrier類的使用,這篇博客中,將會總結Semaphore類的使用,完善Java併發包中的3個工具類的使用總結。
Semaphore
Semaphore是用來控制程序中併發訪問一個特定資源的線程數量,Semaphore通過協調各個線程,從而保證了資源的調度。
- Semaphore的構造器
我們來看一下JDK8中提供的Semaphore構造器。
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
我們看到,在我們創建實例的時候,要傳入一個int類型的參數,這個參數也就是我們可以併發訪問的線程數量。- 應用場景:
Semaphore多用於流量控制,比如是比較重要,特定的資源獲取,eg:數據庫連接。
下面來看一個數據庫連接的demo,demo中,爲線程池定義30個連接,但是Semophore只允許有10個線程併發訪問數據庫連接,並保存數據。我們來看一下代碼實現:
package semaphore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo1 {
private static final int THREAD_COUNT = 30;
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
s.acquire();// 允許並連接
System.out.println("保存數據");
s.release();// 將連接返還給Semaphore
} catch (InterruptedException e) {
}
}
});
}
// 關閉線程池
threadPool.shutdown();
}
}
在控制檯中,會輸出10個“保存數據”,也就是說,雖然線程池雖然允許有30個線程同時運行,但是由於我們在Semaphore中定義了,只允許10個線程同時併發訪問,也就保證了線程的資源訪問安全。- Semaphore提供的方法:
acquire();// 獲取一個許可
release();// 返還給Semaphore一個許可
tryAcquire();//嘗試獲取許可
availablePermits();//返回當前Semophore中可用的許可數量
getQueueLength();//返回正在等待獲取許可的線程數量
hasQueuedThreads();//是否有線程正在等待獲取許可
reducePermits(int reduction)//通過傳入一個reduction參數,來減少Semophore的初始許可數量
Collection<Thread> getQueuedThreads();//返回一個存放所有等待獲取連接的線程集合