Java 信号量(Semaphore) 深入理解

  1. 简介
  2. Semaphore 基础概念
  3. Semaphore 的使用方法
  4. Semaphore 常见实践
  5. Semaphore 最佳实践
  6. 小结
  7. 参考资料

简介

Semaphore,信号量,是一种用于控制对公共资源访问的计数信号装置。信号量管理着一组动态资源的使用,它通过一个计数器限制同时访问资源的线程数量。当计数器大于零时,线程可以访问资源,计数器递减;当计数器为零时,请求资源的线程进入等待状态,直到计数器大于零。

这种机制非常适合用于限制对资源的并发访问数,比如数据库连接、线程池等。

Semaphore 基础概念

Semaphore 可以设定一个许可证数量,用于表示可以访问的资源数目。当线程访问共享资源时,需要先从 Semaphore 处获取许可证,访问完毕后归还许可证。此外,Semaphore 也能实现公平性,即按照请求顺序分配许可证。

Java 的 Semaphore 位于 java.util.concurrent 包中,提供了一个灵活的信号量实现。

Semaphore 的使用方法

构造函数

Java 的 Semaphore 提供了两种构造函数:

  1. Semaphore(int permits): 创建具有指定许可证数量的 Semaphore,非公平模式。
  2. Semaphore(int permits, boolean fair): 第二个参数为布尔值,指示是否使用公平模式。
Semaphore semaphore = new Semaphore(3); // 非公平模式
Semaphore fairSemaphore = new Semaphore(3, true); // 公平模式

常用方法

  • void acquire() throws InterruptedException: 获取一个许可证,若无可用许可证,则线程进入等待。
  • void release(): 归还一个许可证。
  • int availablePermits(): 返回当前可用的许可证数量。
  • boolean tryAcquire(): 尝试获取一个许可证,若获取成功则返回 true,否则返回 false。

Semaphore 常见实践

限制对资源的访问

假设我们需要限制同时访问某个服务的线程数:

import java.util.concurrent.Semaphore;

public class Service {
    private final Semaphore semaphore = new Semaphore(5);

    public void performAction() {
        try {
            semaphore.acquire();
            // 执行业务逻辑
            System.out.println(Thread.currentThread().getName() + " is accessing the service.");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release();
        }
    }
}

实现简单连接池

下面是一个简单的数据库连接池实现,用于限制并发访问数据库连接的数量:

import java.sql.Connection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Semaphore;

public class ConnectionPool {
    private final ArrayBlockingQueue<Connection> pool;
    private final Semaphore semaphore;

    public ConnectionPool(int size) {
        this.pool = new ArrayBlockingQueue<>(size);
        this.semaphore = new Semaphore(size);
        // 初始化连接池,向队列中添加 Connection 对象
    }

    public Connection getConnection() throws InterruptedException {
        semaphore.acquire();
        return pool.take();
    }

    public void releaseConnection(Connection connection) {
        pool.offer(connection);
        semaphore.release();
    }
}

Semaphore 最佳实践

  1. 选择合适的公平策略:非公平的 Semaphore 通常具有更高的吞吐量,但公平策略能避免线程饥饿,需要根据具体需求选择。
  2. 确保许可证的释放:在 finally 块中释放许可证,以确保即使发生异常也能正确释放。
  3. 避免过多等待线程:许可证过少可能导致大量线程长期等待,降低系统性能,需要合理设置初始许可证数量。

小结

Java Semaphore 是一个强大的并发工具,能够有效地限制对共享资源的并发访问。通过本文的介绍,我们深入了解了 Semaphore 的基本概念、使用方法、常见实践以及最佳实践。在实际开发中,合理应用 Semaphore 可以大大提升系统的稳定性与可靠性。

参考资料

posted @   szz1  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示