Semaphore信号量

# Semaphore信号量
Semaphore信号量


  • Semaphore 可以用来限制或管理数量有限资源的使用情况
  • 信号量的作用是用来维护一个“许可证”,的计数,线程可以获取 许可证,那信号量剩余许可证就减一,线程也可以是否一个许可证,那剩余的许可证就加一,当信号量拥有的许可证为0时,那么下一个线程想获得许可证,就要进行等待,直到另外线程释放许可证



信号量使用流程
: 1.初始化Semaphore 并指定许可证的数量
: 2.在需要被现在的代码前加acquire() 或者 acquireUninterruptibly()方法
: 3.在任务结束后,调用release() 来释放许可证

信号量主要方法使用
: 1.new Semaphore(int permits,boolean fair): 这里可以设置是否使用公平策略,如果传入true,那么Semaphore 会把之前等待的线程放到FIFO的队列里,以便于当有了新的许可证,可以分发给之前等了最长时间的线程
: 2.tryAcquire() : 看看现在有没有空闲的许可证,如果有的话就获取,如果没有的话也没关系,我不必陷入阻塞,我可以i去做别的事情,过一会再来查看许可证的空闲情况
: 3.tryAcquire(timeout) : 和tryAcquire()一样,但是多了超时时间,比如 “在3秒内获取不到许可证,我去做别的事情”

  • 代码演示
package com.yxl.task;


import lombok.SneakyThrows;
import org.omg.PortableInterceptor.INACTIVE;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.*;

/**
 * Semaphore 演示demo
 */
public class SemaphoreDemo {

     static Semaphore semaphore =new Semaphore(3,true);
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(50);
        for (int i = 0; i < 50; i++) {
            executorService.execute(new Task());
        }
        executorService.shutdown();

    }
    static class Task implements Runnable{
        @SneakyThrows
        @Override
        public void run() {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName()+"拿到来许可证");
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName()+"释放了许可证");
            semaphore.release();
        }
    }
}

Semaphore信号量
运行结果,会发现他是3个那到,三个释放 执行线程

我们修改获取信号量到参数

@SneakyThrows
        @Override
        public void run() {
            semaphore.acquire(3);
            System.out.println(Thread.currentThread().getName()+"拿到来许可证");
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName()+"释放了许可证");
            semaphore.release(3);
        }

每次运行一个线程都会拿到3个许可证
Semaphore信号量

  • 可以根据我们到需求一次获取或者释放多个许可证
  • 比如TaskA会调用很消耗资源到 method1() 而TaskB 调用到是不太消耗资源到 mehod2(), 假设我们一共有5个许可证,那么我们就可以要求TaskA 获取5个许可证才能执行,这样避免了A B 同时运行到情况,我们可以根据直接到需求和里分配资源


注意点
: 1.获取和释放到许可证数量必须一致,否则比如每次都获取2个但是只释放一个甚至不释放,随着时间到推移,到最后许可证数量不够用,会导致程序卡死。

: 2.注意在初始化Semaphore的时候设置公平性,一般设置为 true 更合理

: 3.信号量的作用,除了控制临界区最多同时有N个线程访问外,林一个作用是可以实现“条件等待”,例如 线程1需要在线程2完成准备工作后才能开始工作,那么线程1 acquire() , 而线程2完成任务后release(),这样电话,相当于轻量级的CountDownLatch

个人博客地址:http://blog.yanxiaolong.cn/

上一篇:SpringCloud--微服务架构


下一篇:手写类似dubbo的rpc框架第二章《netty通信》