Smaphor(信號量)實現限流器

Semaphore信號量java

在管程被提出來以前用的是信號量。服務器

信號量模型

一個計數器,一個等待隊列,三個方法。計數器和等待隊列對外是透明的,因此只能經過信號量模型提供的三個方法來訪問他們,這三個方法分別是:init()、down()、up()併發

  • init():設置計數器的初始值
  • down(): 計數器的值減1; 若是此時計數器的值小於0,則當前線程被阻塞,不然當前線程繼續執行
  • up(): 計數器的值加1;若是此時計數器的值小於或等於0,則歡迎等待隊列中的一個線程,並將其從等待隊列中移除。

這三個方法都是原子性的,原子性是由信號量模型的實現方保證的。在Java SDK裏面,信號量模型是由java.util.concurrent.Semaphore實現的,Semaphore這個類可以保證這 三個方法都是原子操做。app

白話計數器
  1. 計數器記錄設置請求的併發數。
  2. 服務器接受一個請求計數器-1。
  3. 當計數器等於0時請求進入等待隊列等待。
  4. 當服務器處理完一個請求計數器+1(上限時計數器的初始值,最大也只能是計數器的初始值)

親手實現一個信號量

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

相關文章
相關標籤/搜索