Bootstrap

java多线程——Semaphore信号量

Semaphore(信号量)是Java并发工具包(java.util.concurrent)中提供的一个同步辅助类,用于控制对某个资源的访问数量。它允许一个或多个线程同时访问某个特定的资源或资源池,但是可以通过设置许可的数量来限制并发访问的数量

基本工作原理

Semaphore的工作原理是基于许可的概念。在创建Semaphore对象时,你需要指定一个许可的数量,这个数量表示同时能够访问资源的线程数。每个线程在访问资源之前,必须先获得一个许可(通过调用acquire()方法)。如果许可的数量为零,则线程将被阻塞,直到其他线程释放许可(通过调用release()方法)。

主要方法

  • Semaphore(int permits):构造一个Semaphore,并设置初始的许可数量。
  • void acquire():从Semaphore获取一个许可,如果当前没有可用的许可,则当前线程将被阻塞,直到有许可可用。
  • void release():释放一个许可,将其返回给Semaphore。如果有其他线程因为调用acquire()方法而被阻塞,并且当前许可的数量小于最大许可数量,则释放许可可能会唤醒一个被阻塞的线程。
  • tryAcquire():尝试从Semaphore获取一个许可,如果当前有可用的许可,则返回true,并将许可的计数减一;如果当前没有可用的许可,则返回false,并且当前线程不会被阻塞。
  • tryAcquire(long timeout, TimeUnit unit):在指定的时间内尝试从Semaphore获取一个许可。如果在指定的时间内成功获取了许可,则返回true;如果在指定的时间内没有获取到许可,则返回false

使用示例

以下是一个简单的示例,展示了如何使用Semaphore来控制对某个资源的并发访问:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    private static final int MAX_PERMITS = 3; // 最大许可数量
    private final Semaphore semaphore;

    public SemaphoreExample() {
        this.semaphore = new Semaphore(MAX_PERMITS);
    }

    public void accessResource(String threadName) {
        try {
            // 获取许可
            semaphore.acquire();
            // 模拟资源访问
            System.out.println(threadName + " 获取到许可,正在访问资源...");
            Thread.sleep(2000); // 模拟资源访问时间
            System.out.println(threadName + " 访问资源完毕,释放许可...");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // 释放许可
            semaphore.release();
        }
    }

    public static void main(String[] args) {
        SemaphoreExample example = new SemaphoreExample();

        for (int i = 0; i < 5; i++) {
            new Thread(() -> example.accessResource(Thread.currentThread().getName())).start();
        }
    }
}

运行结果

Thread-0 获取到许可,正在访问资源...
Thread-1 获取到许可,正在访问资源...
Thread-2 获取到许可,正在访问资源...
(等待一段时间后)
Thread-0 访问资源完毕,释放许可...
Thread-3 获取到许可,正在访问资源...
(再等待一段时间后)
Thread-1 访问资源完毕,释放许可...
Thread-4 获取到许可,正在访问资源...
(最后)
Thread-2 访问资源完毕,释放许可...
Thread-3 访问资源完毕,释放许可...
Thread-4 访问资源完毕,释放许可...

注意事项

  • Semaphore可以用于保护一个或多个共享资源的访问,确保在任何时候都不会有超过指定数量的线程同时访问这些资源。
  • Semaphore是线程安全的,可以在多个线程中安全地使用。
  • CountDownLatch不同,Semaphore的许可可以被释放和重新获取,因此它适用于需要多次协调资源访问的场景。
  • 在使用Semaphore时,需要确保在最终释放资源时调用release()方法,以避免线程永久阻塞。
;