Java中的Semaphore信号量详解
作者:warybee
这篇文章主要介绍了Java中的Semaphore信号量详解,Semaphore(信号量)是用来控制同时访问特定资源的线程数量,通过协调各个线程以保证合理地使用公共资源,需要的朋友可以参考下
1、介绍
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,通过协调各个线程以保证合理地使用公共资源。
Semaphore通过使用计数器来控制对共享资源的访问。 如果计数器大于0,则允许访问。
如果为0,则拒绝访问。 计数器所计数的是允许访问共享资源的许可。 因此,要访问资源,必须从信号量中授予线程许可。
2、主要方法
- void acquire() :从信号量获取一个许可,如果无可用许可前将一直阻塞等待,
 - void acquire(int permits) :获取指定数目的许可,如果无可用许可前也将会一直阻塞等待
 - boolean tryAcquire():从信号量尝试获取一个许可,如果无可用许可,直接返回false,不会阻塞
 - boolean tryAcquire(int permits): 尝试获取指定数目的许可,如果无可用许可直接返回false
 - boolean tryAcquire(int permits, long timeout, TimeUnit unit): 在指定的时间内尝试从信号量中获取许可,如果在指定的时间内获取成功,返回true,否则返回false
 - void release():释放一个许可,别忘了在finally中使用,注意:多次调用该方法,会使信号量的许可数增加,达到动态扩展的效果,如:初始permits为1,调用了两次release,最大许可会改变为2
 - int availablePermits(): 获取当前信号量可用的许可
 
Semaphore构造函数
 public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
- permits 初始许可数,也就是最大访问线程数
 - fair 当设置为false时,创建的信号量为非公平锁;当设置为true时,信号量是公平锁
 
3、Semaphore登录限流示例
在以下示例中,实现一个简单的登录队列,通过Semaphore来限制系统中的用户数:
public static void main(String[] args) {
        //允许最大的登录数
        int slots=10;
        ExecutorService executorService = Executors.newFixedThreadPool(slots);
        LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots);
        //线程池模拟登录
        for (int i = 1; i <= slots; i++) {
            final int num=i;
            executorService.execute(()->{
                 if (loginQueue.tryLogin()){
                     System.out.println("用户:"+num+"登录成功!");
                 }else {
                     System.out.println("用户:"+num+"登录失败!");
                 }
            });
        }
        executorService.shutdown();
        System.out.println("当前可用许可证数:"+loginQueue.availableSlots());
        //此时已经登录了10个用户,再次登录的时候会返回false
        if (loginQueue.tryLogin()){
            System.out.println("登录成功!");
        }else {
            System.out.println("系统登录用户已满,登录失败!");
        }
        //有用户退出登录
        loginQueue.logout();
        //再次登录
        if (loginQueue.tryLogin()){
            System.out.println("登录成功!");
        }else {
            System.out.println("系统登录用户已满,登录失败!");
        }
    }class LoginQueueUsingSemaphore{
    private Semaphore semaphore;
    /**
     *
     * @param slotLimit
     */
    public LoginQueueUsingSemaphore(int slotLimit){
        semaphore=new Semaphore(slotLimit);
    }
    boolean tryLogin() {
        //获取一个凭证
        return semaphore.tryAcquire();
    }
    void logout() {
        semaphore.release();
    }
    int availableSlots() {
        return semaphore.availablePermits();
    }
}
运行结果:

到此这篇关于Java中的Semaphore信号量详解的文章就介绍到这了,更多相关Semaphore信号量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
