原文: https://javatutorial.net/java-semaphore-example

信号量可用于限制并发线程的数量,并且实质上,此类维护一组许可。

acquire()从信号量获取许可,然后release()将许可返回信号量。 如果没有许可证,则acuire()将阻塞直到可用

信号量用于控制对特定资源的访问。

Java 信号量示例 - 图1

工作流程

信号量设置为一个计数值。 然后线程尝试获取许可,如果计数为 0 或小于 0,则线程将被阻塞,并且它将等待下一个许可(如果有)。 这将一直保持下去,直到数量大于 0。如果是,则信号量将提供对线程资源的访问。 然后线程将释放许可,计数将增加 1。

构造器

  1. Semaphore(int permits):使用给定数量的许可和不公平的公平设置创建一个信号量
  2. Semaphore(int permits, boolean fair):创建具有给定许可数量和给定公平性设置的信号量

主要方法

  1. void acquire():从当前信号量获取许可,阻塞直到可用,否则线程被中断。
  2. void acquire(int permits):从当前信号量获取指定的许可数量,直到所有可用或线程中断为止一直阻塞。
  3. int availablePermites():返回当前信号量中可用的当前许可数量

要查看所有方法,请单击此处,您将被重定向到 Oracle 官方文档

信号量可用于锁定对特定资源的访问。 每个线程都必须请求“权限”,因此需要在访问资源之前调用方法acquire()。 当线程不再需要资源时,它必须调用release()来释放锁。

  1. import java.util.concurrent.Semaphore;
  2. public class SemaphoreDemo {
  3. public static void main(String[] args) throws Exception {
  4. Semaphore semExample = new Semaphore(1);
  5. System.out.println("Available permits: " + semExample.availablePermits());
  6. semExample.release();
  7. System.out.println("Available permits: " + semExample.availablePermits());
  8. semExample.acquire();
  9. System.out.println("Available permits: " + semExample.availablePermits());
  10. semExample.acquire();
  11. System.out.println("Available permits: " + semExample.availablePermits());
  12. semExample.acquire();
  13. System.out.println("Available permits: " + semExample.availablePermits());
  14. }
  15. }

输出

  1. Available permits: 1
  2. Available permits: 2
  3. Available permits: 1
  4. Available permits: 0

从上面的示例中可以看到,当您调用release()时,您正在向Semaphore实例添加许可。 当您调用acquire()时,您正在删除permit()。 如果没有许可证,而您打电话给获取,它将等待直到许可证被释放,因此在上例中将永远不会执行最后一个打印语句。

如果您有 1 个许可,然后又有一个acquire()调用,紧接着是一个release()调用,则称为锁。

  1. import java.util.concurrent.Semaphore;
  2. public class SemaphoreDemo {
  3. Semaphore thread = new Semaphore(1);
  4. public static void main(String args[]) {
  5. final SemaphoreDemo test = new SemaphoreDemo();
  6. new Thread(){
  7. @Override
  8. public void run(){
  9. test.mutualExclusion();
  10. }
  11. }.start();
  12. new Thread(){
  13. @Override
  14. public void run(){
  15. test.mutualExclusion();
  16. }
  17. }.start();
  18. }
  19. private void mutualExclusion() {
  20. try {
  21. System.out.println(Thread.currentThread().getName() + " is waiting to acquire a permit.");
  22. thread.acquire();
  23. System.out.println("Permit has been acquired to " + Thread.currentThread().getName());
  24. Thread.sleep(1000);
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. } finally {
  28. System.out.println(Thread.currentThread().getName() + " is releasing the permit...");
  29. thread.release();
  30. System.out.println("Released.");
  31. }
  32. }
  33. }

输出

  1. Thread-0 is waiting to acquire a permit.
  2. Permit has been acquired to Thread-0
  3. Thread-1 is waiting to acquire a permit.
  4. Thread-0 is releasing the permit...
  5. Released.
  6. Permit has been acquired to Thread-1
  7. Thread-1 is releasing the permit...
  8. Released.

从输出中可以看到,线程 0 允许了一个获取,线程 1 开始等待为其本身获取一个许可,但是它(线程 1)仅在线程 0 释放其许可时才获得它。