Java里如何使用Semaphore实现信号量控制_Semaphore资源访问控制方法解析

Semaphore通过许可机制限制并发访问线程数,acquire()获取许可,release()释放许可,确保资源安全。

在Java中,Semaphore 是并发编程中用于控制对共享资源访问数量的工具类,常用于限流、资源池管理等场景。它通过维护一组许可(permits)来限制同时访问特定资源的线程数量。

Semaphore的基本原理

Semaphore内部维护了一个计数器,表示可用许可的数量。线程在访问资源前必须先获取许可,如果当前没有可用许可,线程将被阻塞,直到其他线程释放许可为止。

主要方法包括:

  • acquire():尝试获取一个许可,如果没有可用许可,线程会阻塞。
  • acquire(int permits):一次获取多个许可。
  • release():释放一个许可,使其他等待的线程有机会获得许可。
  • release(int permits):一次释放多个许可。
  • availablePermits():返回当前可用的许可数。

简单使用示例:限制并发线程数

假设我们有一个服务最多允许3个线程同时访问,可以使用Semaphore进行控制:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    // 定义一个拥有3个许可的Semaphore
    private static final Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 尝试获取许可");
                    semaphore.acquire(); // 获取许可
                    System.out.println(Thread.currentThread().getName() + " 获得许可,开始执行任务");

                    // 模拟任务执行
                    Thread.sleep(2000);

                    System.out.println(Thread.currentThread().getName() + " 任务完成,释放许可");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    semaphore.release(); // 释放许可
                }
            }, "Thread-" + i).start();
        }
    }
}

在这个例子中,尽管启动了5个线程,但只有3个能同时运行,其余线程需等待许可释放后才能执行。

应用场景与注意事项

Semaphore适用于以下场景:

  • 数据库连接池控制:限制最大连接数。
  • API调用限流:防止系统被过多请求压垮。
  • 硬件资源访问:如打印机、传感器等有限设备的并发访问控制。

使用时需要注意:

  • 确保每次acquire()后都有对应的release(),建议放在finally块中,避免死锁或资源泄露。
  • 初始化许可数应根据实际资源容量设置,过大失去限流意义,过小影响并发性能。
  • Semaphore默认是非公平的,可传入true构造公平模式,避免线程饥饿。

基本上就这些,掌握好acquire和release的配对使用,就能有效实现资源的并发控制。不复杂但容易忽略细节。