如何通过信号量机制构建一个高效的限流器?

2026-05-27 12:462阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计806个文字,预计阅读时间需要4分钟。

如何通过信号量机制构建一个高效的限流器?

(1)符号量是什么?符号量是65岁斯图亚特·诺特提出来的,一直用到80年左右。左右都是用它来解决并发展的问题,直到管程模型出来后,它就逐渐退出了。符号量你可以类比生活中的红绿灯,红绿灯行红停绿。

1)什么是信号量呢?

  • 65年斯特拉提出来信号量,一直用到80年左右都是用它来解决并发的问题,直到管程模型出来了,他就逐渐落魄了。信号量你可以类比生活中的红绿灯,绿灯行红灯停。

2)信号量模型是怎样的?

  • 一个计数器,一个等待队列,3个方法(init(),up(),dowm())

3)信号量的工作原理是什么?

  • 当线程进临界资源的时候,先把count-1,然后看是不是<0的,如果<0那么对不起,不能进入 ,老老实实进等待队列去。如果>=0,那么可以进入,出来的时候把count+1,当count>=0了,那么就去唤醒等待队列的一个线程。

4)有了管程了,那信号量还有存在的意义吗?

  • 有,信号量他有自己的不可替代性,他允许多个线程进入临界资源,这个对我们的池化技术实现是有很大帮助的,比如我们的数据库连接池,对象池。

5)如何用信号量快速实现一个限流器?

  • 比如现在我们的需求是10个线程为上限,超过10个就限制进入。那我可以这样设计,count初始化为10,那么我10个线程拿到count的时候,都是>=0的,第11个线程来的时候,把count-1,count=-1小于0了,所以进等待队列去。

    如何通过信号量机制构建一个高效的限流器?


    class ObjPool<T, R> {
    final List<T> pool;
    // 用信号量实现限流器
    final Semaphore sem;
    // 构造函数
    ObjPool(int size, T t){
    pool = new Vector<T>(){};
    for(int i=0; i<size; i++){
    pool.add(t);
    }
    sem = new Semaphore(size);
    }
    // 利用对象池的对象,调用func
    R exec(Function<T,R> func) {
    T t = null;
    sem.acquire();
    try {
    t = pool.remove(0);
    return func.apply(t);
    } finally {
    pool.add(t);
    sem.release();
    }
    }
    }
    // 创建对象池
    ObjPool<Long, String> pool =
    new ObjPool<Long, String>(10, 2);
    // 通过对象池获取t,之后执行
    pool.exec(t -> {
    System.out.println(t);
    return t.toString();
    });

6)思考一下,上面的限流器使用的是vector来做对象集合的,那可不可以用ArrayList呢?

  • 不可以的,ArrayList是线程不安全的,而我们上面的对象池他是允许多个线程进入来访问的,不用vector的话容易引发线程故障。造成并发执行了。

本文共计806个文字,预计阅读时间需要4分钟。

如何通过信号量机制构建一个高效的限流器?

(1)符号量是什么?符号量是65岁斯图亚特·诺特提出来的,一直用到80年左右。左右都是用它来解决并发展的问题,直到管程模型出来后,它就逐渐退出了。符号量你可以类比生活中的红绿灯,红绿灯行红停绿。

1)什么是信号量呢?

  • 65年斯特拉提出来信号量,一直用到80年左右都是用它来解决并发的问题,直到管程模型出来了,他就逐渐落魄了。信号量你可以类比生活中的红绿灯,绿灯行红灯停。

2)信号量模型是怎样的?

  • 一个计数器,一个等待队列,3个方法(init(),up(),dowm())

3)信号量的工作原理是什么?

  • 当线程进临界资源的时候,先把count-1,然后看是不是<0的,如果<0那么对不起,不能进入 ,老老实实进等待队列去。如果>=0,那么可以进入,出来的时候把count+1,当count>=0了,那么就去唤醒等待队列的一个线程。

4)有了管程了,那信号量还有存在的意义吗?

  • 有,信号量他有自己的不可替代性,他允许多个线程进入临界资源,这个对我们的池化技术实现是有很大帮助的,比如我们的数据库连接池,对象池。

5)如何用信号量快速实现一个限流器?

  • 比如现在我们的需求是10个线程为上限,超过10个就限制进入。那我可以这样设计,count初始化为10,那么我10个线程拿到count的时候,都是>=0的,第11个线程来的时候,把count-1,count=-1小于0了,所以进等待队列去。

    如何通过信号量机制构建一个高效的限流器?


    class ObjPool<T, R> {
    final List<T> pool;
    // 用信号量实现限流器
    final Semaphore sem;
    // 构造函数
    ObjPool(int size, T t){
    pool = new Vector<T>(){};
    for(int i=0; i<size; i++){
    pool.add(t);
    }
    sem = new Semaphore(size);
    }
    // 利用对象池的对象,调用func
    R exec(Function<T,R> func) {
    T t = null;
    sem.acquire();
    try {
    t = pool.remove(0);
    return func.apply(t);
    } finally {
    pool.add(t);
    sem.release();
    }
    }
    }
    // 创建对象池
    ObjPool<Long, String> pool =
    new ObjPool<Long, String>(10, 2);
    // 通过对象池获取t,之后执行
    pool.exec(t -> {
    System.out.println(t);
    return t.toString();
    });

6)思考一下,上面的限流器使用的是vector来做对象集合的,那可不可以用ArrayList呢?

  • 不可以的,ArrayList是线程不安全的,而我们上面的对象池他是允许多个线程进入来访问的,不用vector的话容易引发线程故障。造成并发执行了。