信號量用來控制有限資源的方法,舉例:假如信號量為3,則同時只有3個線程共享。
概述
信號量用來控制系統耗時資源的訪問,一般我們初始設置了一個公平的信號量,線程在使用時需要申請,用完之后需要釋放。
使用流程
信號量Semaphore的使用流程如下:
一般設置公平的信號量-->線程在使用時需要進行require申請-->若可以申請到,則執行自己的邏輯-->執行完成后,需要釋放信號量
-->若未申請到,則可以阻塞,直到申請到。
主要方法
信號量的部分常用方法如下:
1.信號量構造:public Semaphore(int permits, boolean fair)
2.獲取信號量:public void acquire();acquireUninterruptibly();tryAcquire() ;tryAcquire(long timeout, TimeUnit unit)
3.釋放信號量:release();release(int permits)
實例代碼
下面我們通過初始化一個3容量的信號量,我們用100個線程去獲取這個信號量,每次申請一個信號量,當用完之后,我們釋放這一個,如以下實例代碼所示:
package com.yang.concurrent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.stream.IntStream; public class SemaphoreDemp { static Semaphore semaphore =new Semaphore(3,true); public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) { Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()+"等待獲取信號量"); semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"取到了信號量"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally { System.out.println(Thread.currentThread().getName()+"釋放信號量"); semaphore.release(); } } }; executorService.submit(runnable); } executorService.shutdown(); } }
運行結果如下圖所示:
特殊用法及注意點
1.申請和釋放的信號量必須保持一致,在信號量申請時,比如我們可以申請2個,釋放的時候也可以釋放2個,這個場景是指程序在運行時,可能需要多個資源
2.信號量在初始化的時候,可以設置為公平或者非公平,我們一般設置為公平,對耗時長的資源訪問時,一般不允許爭奪
3.信號量在獲取和釋放時,對是否是同一個線程沒有限制。