Semaphore信號量java
在管程被提出來以前用的是信號量。服務器
一個計數器,一個等待隊列,三個方法。計數器和等待隊列對外是透明的,因此只能經過信號量模型提供的三個方法來訪問他們,這三個方法分別是:init()、down()、up()併發
這三個方法都是原子性的,原子性是由信號量模型的實現方保證的。在Java SDK裏面,信號量模型是由java.util.concurrent.Semaphore實現的,Semaphore這個類可以保證這 三個方法都是原子操做。app
import java.util.Queue; /** * 信號量 **/ public class Semaphore { //計數器 int count; //等待隊列 Queue<String> queue; //初始化操做 Semaphore(int count){ this.count = count; } void down(){ this.count--; if (this.count<0){ //將當前線程插入等待隊列 //阻塞當前線程 } } void up(){ this.count ++ ; if (this.count>=0){ //移出等待隊列中的某個線程T //喚醒線程T } } }
在JavaSDK併發包裏,down()和up()對應的則是acquire()和release()。ui
實現一個限流器:this
import java.util.List; import java.util.Vector; import java.util.concurrent.Semaphore; import java.util.function.Function; /** * * **/ public class ObjPool<T,R> { //對象池 final List<T> pool; //信號量 final Semaphore sem; /** * 向線程池裏添加數據 * @param size 對象數量 * @param t */ public ObjPool(int size, T t) { this.pool = new Vector<>(); for (int i=0; i<size;i++){ pool.add(t); } sem = new Semaphore(size); } R exec(Function<T,R> func) throws Exception{ T t = null; sem.acquire();//計數器 -1 try { t = pool.remove(0);//從隊列中去除一個值 return func.apply(t); }finally { pool.add(t); sem.release();//計數器+1 } } public static void main(String[] args) throws Exception{ ObjPool<Long, String> pool = new ObjPool<>(10, 2L); pool.exec(t -> { System.out.println(t); return t.toString(); }); } }
**** 碼字不易若是對你有幫助請給個關注****線程
**** 愛技術愛生活 QQ羣: 894109590****code