首页 > 编程语言 >Java 并发工具类之 Semaphore

Java 并发工具类之 Semaphore

时间:2023-12-30 10:36:29浏览次数:36  
标签:Java int void Semaphore 并发 线程 许可证 public


Semaphore 控制访问特定资源的线程数量,新建规定数量的许可证,获得许可证可以继续执行,未获得需要阻塞,执行完成归还许可证,这样其余的线程(未获得许可证)才可以执行。例如:Semaphore用于流量控制,例如只有10个数据库连接,可以用Semaphore控制只有10个线程访问数据库,这样就不会报错无法获取数据库连接。

 1. Semaphore的部分方法

方法

描述

public Semaphore(int permits)

构造函数:设置许可证数permits。

public Semaphore(int permits, boolean fair)

设置许可证数permits, fair 为 true 使用先进先出的公平策略,false则不公平。

public void acquire()

获取许可证。

public void acquireUninterruptibly() 

不可中断的获取许可证。

public boolean tryAcquire()

尝试获取许可证,没有许可证不阻塞

public boolean tryAcquire(long timeout, TimeUnit unit)

等待一定时间,一直没有获得许可证不再阻塞

public void release()

归还许可证

public void acquire(int permits)

获取给定数量的许可证

public void release(int permits)

归还给定数量的许可证

public final boolean hasQueuedThreads()

是否有线程在等待

public final int getQueueLength()

等待线程的数量

protected Collection<Thread> getQueuedThreads()

返回所有等待许可的线程集合

public int availablePermits()

剩余许可证

2. 测试代码

许可证数量初始为 3 。

private static Semaphore semaphore = new Semaphore(3);

测试代码如下所示,开启10个线程获取数据库连接,因为只有三个许可证,三个许可证被获取后,其他线程需要等待当前的三个线程释放许可证才可以获取许可证,所以三个数据库连接、三个数据库连接被获取: 

public class SemaphoreStudy implements Runnable{
    private static Semaphore semaphore = new Semaphore(3);

    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.print("获得数据库连接");
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        semaphore.release();
    }

    public static void main(String[] args) {
        for (int i=0; i<10; i++) {;
            new Thread(new SemaphoreStudy()).start();
        }
    }
}

运行截图,三个、三个数据库连接被获取。

Java 并发工具类之 Semaphore_数据库连接

使用 tryAcquire() 进行修改, tryAcquire() 尝试获取许可证,没有许可证不阻塞,测试代码如下:

public class SemaphoreStudy implements Runnable{
    private static Semaphore semaphore = new Semaphore(3);

    @Override
    public void run() {
        try {
            if (semaphore.tryAcquire()) {
                System.out.println("获得数据库连接");
                TimeUnit.MILLISECONDS.sleep(1000);
                semaphore.release();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        for (int i=0; i<10; i++) {;
            new Thread(new SemaphoreStudy()).start();
        }
    }
}

运行截图,7个获取不到许可证的线程,不阻塞等待:

Java 并发工具类之 Semaphore_i++_02

标签:Java,int,void,Semaphore,并发,线程,许可证,public
From: https://blog.51cto.com/xuxiangyang/9038467

相关文章

  • Java线程池的学习
    线程池有如下四个优点:降低资源消耗: 重用已经创建的线程, 线程的创建和销毁需要消耗计算机资源,特别是在有大量创建线程请求且线程的处理过程是轻量级的,例如:大多数的服务器。提高响应速度:重用已经创建的线程。提高线程的稳定性:可创建的线程数量是由有限制的,限制值是有多个因素制约,例......
  • Java 中的继承
    继承:可以基于已存在的类构造一个新类,继承已存在的类就是复用(继承)这些类的方法和域,在此基础上,还可以添加一些新的方法和域。1. 继承性 继承性: 把多种有着共同特性的多的类事物抽象成一个类,这个类就是多个类的父类。父类的意义在于可以抽取多个类的共性,代码复用,减少代码量。例:三个......
  • Java中的抽象类
    抽象类必须使用abstract关键声明,例如抽象类MyAbstractStudy:publicabstractclassMyAbstractStudy{}不能使用抽象类创建对象。抽象类中可以没有抽象方法。抽象方法必须为public或者protected,缺省情况下为public。抽象类的子类必须实现父类的抽象方法,如果没有则需要声明子类也为ab......
  • Java8 原子类 AtomicInteger 源码阅读
    AtomicInteger 是用 CAS(Compre And Swap,乐观锁)构造的一个 原子类。1. CAS CAS(CompareandSwap)比较并替换,CAS是实现乐观锁的一个重要操作。CAS是一个硬件指令,保证是原子操作,Java中通过UnSafe来实现。详细可一下我的这篇博文:传送。CAS 的基本步骤:执行函数CAS(V,E,N......
  • java-关键字与方法(二)
    charAt() 方法:charAt() 方法返回字符串中指定索引处的字符。示例:Stringstr="HelloWorld";charch=str.charAt(4);//ch的值为'o'在上面的例子中,charAt()方法返回字符串str中索引为4的字符,即字母'o'。length() 方法:length() 方法返回字符串的长度。示例......
  • 无涯教程-Java 正则 - Pattern quote(String s)函数
    java.util.regex.Pattern.quote(Strings)方法返回指定String的文字模式。staticStringquote-声明publicstaticStringquote(Strings)s  - 要被字符串化的字符串。staticStringquote-返回值文字字符串替换。staticStringquote-示例下面的示例显示ja......
  • 无涯教程-Java 正则 - Pattern String[] split(CharSequence input)函数
    java.util.regex.Pattern.split(CharSequenceinput)方法将给定的输入序列拆分为该模式的匹配项。String[]split-声明publicString[]split(CharSequenceinput)input  - 要拆分的字符序列。String[]split-返回值通过在此模式的匹配项附近拆分输入来计算的字符......
  • JavaScript的apply、call、bind方法
    JavaScript的apply、call、bind方法概述简述这三个方法存在一定的迷惑性,而且对于刚看ES6的人来说,十分难理解,这里为了以后我可能会复习到这个知识点,做出详解。总的来说,这三个方法都是将某某某(某01)绑定在某某某(某02)上,然后执行这个被绑定的某某某(某01),或者单纯就是绑定不执行。详......
  • 无涯教程-Java 正则 - Matcher matcher(CharSequence input)函数
    java.util.regex.Pattern.matcher(CharSequenceinput)方法创建一个匹配器,该匹配器将根据该模式匹配给定的输入。Matchermatcher-声明publicMatchermatcher(CharSequenceinput)input  - 要匹配的字符序列。Matchermatcher-返回值此模式的新匹配器。Matcher......
  • java-关键字与方法(一)
    synchronized关键字:synchronized关键字用于实现互斥访问共享资源的同步机制。它可以应用于方法或代码块。当一个线程进入synchronized代码块时,它将获得锁,其他线程必须等待锁释放才能执行该代码块。synchronized关键字确保了同一时间只有一个线程可以执行被保护的代码块,从而避免......