Java中的Semaphore信号量的使用方法
创始人
2024-12-25 13:04:04
0次

  Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

  Semaphore

  Semaphore 有两个构造函数,参数为许可的个数 permits 和是否公平竞争 fair。通过 acquire 方法能够获得的许可个数为 permits,如果超过了这个个数,就需要等待。当一个线程 release 释放了一个许可后,fair 决定了正在等待的线程该由谁获取许可,如果是公平竞争则等待时间最长的线程获取,如果是非公平竞争则随机选择一个线程获取许可。不传 fair 的构造函数默认采用非公开竞争。

  Semaphore(int permits)

  Semaphore(int permits, boolean fair)

  一个线程可以一次获取一个许可,也可以一次获取多个。 在 acquire 等待的过程中,如果线程被中断,acquire 会抛出中断异常,如果希望忽略中断继续等待可以调用 acquireUninterruptibly 方法。同时提供了 tryAcquire 方法尝试获取,获取失败返回 false,获取成功返回 true。tryAcquire 方法可以在获取不到时立即返回,也可以等待一段时间。需要注意的是,没有参数的 tryAcquire 方法在有许可可以获取的情况下,无论有没有线程在等待都能立即获取许可,即便是公平竞争也能立即获取。

  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 acquireUninterruptibly(int permits)

  public boolean tryAcquire(int permits)

  public boolean tryAcquire(int permits, long timeout, TimeUnit unit)

  public void release(int permits)

  使用示例

  如下的示例中,测试方法 test 创建了多个线程,每个线程启动后都调用 acquire 方法,然后延时 5s 模仿业务耗时,最后调用 release 方法释放许可。

  public class SemaphoreTest {

  private int threadNum;

  private Semaphore semaphore;

  public SemaphoreTest(int permits,int threadNum, boolean fair) {

  this.threadNum = threadNum;

  semaphore = new Semaphore(permits,fair);

  }

  private void println(String msg){

  SimpleDateFormat sdf = new SimpleDateFormat("[YYYY-MM-dd HH:mm:ss.SSS] ");

  System.out.println(sdf.format(new Date()) + msg);

  }

  public void test(){

  for(int i = 0; i < threadNum; i ++){   new Thread(() -> {

  try {

  semaphore.acquire();

  println(Thread.currentThread().getName() + " acquire");

  Thread.sleep(5000);//模拟业务耗时

  println(Thread.currentThread().getName() + " release");

  semaphore.release();

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }).start();

  }

  }

  }

  公平与非公平

  在上述的示例中,如果 fair 传的是 true,则各个线程公平竞争,即按照等待时间的长短决定谁先获取许可。以 9 个线程竞争 3 个许可为例,执行结果如下,首选是线程 0、1、2 获取了许可,5s 后线程 3、4、5 获取了许可,最后是线程 6、7、8 获取许可,顺序基本上与创建线程并启动的先后顺序一致,也与各个线程等待的时间基本相符。

  [2017-08-20 21:47:21.817] Thread-0 acquire

  [2017-08-20 21:47:21.817] Thread-2 acquire

  [2017-08-20 21:47:21.817] Thread-1 acquire

  [2017-08-20 21:47:26.830] Thread-1 release

  [2017-08-20 21:47:26.830] Thread-0 release

  [2017-08-20 21:47:26.830] Thread-4 acquire

  [2017-08-20 21:47:26.830] Thread-3 acquire

  [2017-08-20 21:47:26.831] Thread-2 release

  [2017-08-20 21:47:26.831] Thread-5 acquire

  [2017-08-20 21:47:31.831] Thread-4 release

  [2017-08-20 21:47:31.831] Thread-3 release

  [2017-08-20 21:47:31.831] Thread-6 acquire

  [2017-08-20 21:47:31.831] Thread-7 acquire

  [2017-08-20 21:47:31.832] Thread-5 release

  [2017-08-20 21:47:31.832] Thread-8 acquire

  [2017-08-20 21:47:36.831] Thread-6 release

  [2017-08-20 21:47:36.831] Thread-7 release

  [2017-08-20 21:47:36.832] Thread-8 release

  在上述的示例中,如果 fair 传的是 false,则各个线程非公平竞争,随机选取一个线程获取许可。以 9 个线程竞争 3 个许可为例,执行结果如下,首先是线程 0、1、3 获取了许可,5s 后线程 2、5、7 获取了许可,最后是线程 4、6、8 获取许可,与线程创建启动时间无关,也与线程等待时间无关。

  [2017-08-20 17:45:09.893] Thread-0 acquire

  [2017-08-20 17:45:09.893] Thread-3 acquire

  [2017-08-20 17:45:09.893] Thread-1 acquire

  [2017-08-20 17:45:14.895] Thread-3 release

  [2017-08-20 17:45:14.895] Thread-0 release

  [2017-08-20 17:45:14.895] Thread-5 acquire

  [2017-08-20 17:45:14.895] Thread-1 release

  [2017-08-20 17:45:14.896] Thread-7 acquire

  [2017-08-20 17:45:14.896] Thread-2 acquire

  [2017-08-20 17:45:19.895] Thread-5 release

  [2017-08-20 17:45:19.895] Thread-4 acquire

  [2017-08-20 17:45:19.896] Thread-7 release

  [2017-08-20 17:45:19.896] Thread-6 acquire

  [2017-08-20 17:45:19.896] Thread-2 release

  [2017-08-20 17:45:19.896] Thread-8 acquire

  [2017-08-20 17:45:24.895] Thread-4 release

  [2017-08-20 17:45:24.896] Thread-8 release

  [2017-08-20 17:45:24.896] Thread-6 release

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...