美文网首页
J.U.C 之 Semaphore 简单应用

J.U.C 之 Semaphore 简单应用

作者: 吉他手_c156 | 来源:发表于2020-06-24 11:37 被阅读0次

Semaphore(信号量),是一种计数器,用来保护一个或者多个共享资源的访问,如果线程要访问一个资源就必须先获得信号量,如果信号量内部计数器大于 0 ,信号量减 1,然后允许共享这个资源,否则,如果信号量的计数器等于 0,信号量会把线程置入休眠,直至计数器大于 0,当信号量使用完时,必须释放

构造方法

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 时,信号量时公平模式

主要的方法

  • 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(): 获取当前信号量可用的许可

Semophore 模拟简单限流场景

public class SemaphoreDemo{

    public static void main(String[] args) {
        // 令牌数最大 5 个,没有令牌无法访问
        Semaphore semaphore = new Semaphore(5);
        // 模拟 50 个线程,每次最多 5 个线程访问
        for (int i = 0; i < 50; i++) {
            new Thread(new Car(semaphore,i)).start();
        }
    }

    static class Car implements Runnable{
        Semaphore semaphore;
        int num;
        public Car(Semaphore semaphore,int num){
            this.semaphore = semaphore;
            this.num = num;
        }
        @Override
        public void run() {
            try {
                semaphore.acquire(); // 获得令牌,如果没有获取到令牌 阻塞
                System.out.println("第"+num+"个线程占用了一个令牌");
                // 模拟访问时间
                Thread.sleep(3000);
                System.out.println("第"+num+"个线程释放了一个令牌");
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                semaphore.release(); // 释放令牌
            }
        }
    }
}

结果

第1个线程占用了一个令牌
第3个线程占用了一个令牌
第5个线程占用了一个令牌
第7个线程占用了一个令牌
第9个线程占用了一个令牌
第3个线程释放了一个令牌
第1个线程释放了一个令牌
第11个线程占用了一个令牌
第13个线程占用了一个令牌
第5个线程释放了一个令牌
第15个线程占用了一个令牌
第9个线程释放了一个令牌
第7个线程释放了一个令牌
第17个线程占用了一个令牌
第19个线程占用了一个令牌
第11个线程释放了一个令牌
......

相关文章

网友评论

      本文标题:J.U.C 之 Semaphore 简单应用

      本文链接:https://www.haomeiwen.com/subject/witrfktx.html