JUC工具类: Semaphore详解

简介: 信号量Semaphore是并发编程中的一种高级同步机制,它可以在复杂的资源共享场景中发挥重要作用。理解它的工作原理及正确的使用方法对实现高效且健壮的并发控制至关重要。

在并发编程中,Semaphore(信号量)是一种重要的同步辅助类,用于控制对共享资源的访问。它是java.util.concurrent(JUC)包提供的工具之一,在Java语言中被广泛应用。Semaphore的核心思想是维护一组许可证,它可以控制同时访问特定资源的线程数量。

Semaphore的工作原理

Semaphore管理一系列许可证(permits),线程可以通过 acquire()方法来获取许可证,如果Semaphore持有足够的许可证,则允许线程的执行,如果没有,则线程需要等待,直到有线程释放许可证。线程执行完毕后,应调用 release()方法来释放许可证,以供其他线程使用。

Semaphore的主要方法

  • acquire(): 请求一个许可证。如果许可证不可用,当前线程将被阻塞,直到有许可证被释放。
  • acquire(int permits): 请求给定数量的许可证。
  • release(): 释放一个许可证,将其返回给Semaphore。
  • release(int permits): 释放多个许可证。
  • tryAcquire(): 尝试获取一个许可证,如果没有可用的许可证,立即返回false。
  • tryAcquire(long timeout, TimeUnit unit): 尝试在给定时间内获取许可证,如果在指定的时间内没有获取到,返回false。

Semaphore的应用场景

Semaphore常被用于资源池(如数据库连接池、线程池)的管理,保证有限的资源被合理地分配。它也可以用来实现某些特殊的同步需求,比如限流,即限制某段时间内的访问量。

一个简单的Semaphore示例

下面举例说明如何使用Semaphore来控制对资源的访问:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    // 创建Semaphore实例并指定许可证数量为5
    private static final Semaphore semaphore = new Semaphore(5);

    public static void main(String[] args) {
        // 模拟有10个线程同时请求访问资源
        for (int i = 0; i < 10; i++) {
            new Thread(new Worker(i)).start();
        }
    }

    static class Worker implements Runnable {
        private int num;

        public Worker(int num) {
            this.num = num;
        }

        @Override
        public void run() {
            try {
                // 请求许可证
                semaphore.acquire();
                System.out.println("线程" + num + "获取许可证,当前可用许可证数量:" + semaphore.availablePermits());

                // 模拟业务操作,线程睡眠2秒
                Thread.sleep(2000);

                // 释放许可证
                semaphore.release();
                System.out.println("线程" + num + "释放许可证,当前可用许可证数量:" + semaphore.availablePermits());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个示例中,我们定义了一个Semaphore,它持有5个许可证。然后,启动了10个线程要求访问共享资源。当一个线程开始运行时,它会尝试通过 acquire()方法从Semaphore获取许可证,如果获取到许可证,线程将执行,并在完成后释放许可证。如果许可证全部被其他线程持有,后来的线程将被阻塞,直到有许可证释放。

注意事项和最佳实践

  1. 确保资源的使用量不会超过Semaphore允许的许可证数目。
  2. 经典的错误是忘记释放许可证,这将导致其他线程无法访问资源。
  3. 尽量使用 tryAcquire带有超时的重载版本,避免永久等待资源的情况发生。
  4. 在使用Semaphore时,建议在 finally代码块中释放许可证,确保许可证总能被释放。
  5. Semaphore不跟踪哪个线程获取了许可证,因此任何线程都可以释放许可证,这点在设计同步策略时需要注意。

信号量Semaphore是并发编程中的一种高级同步机制,它可以在复杂的资源共享场景中发挥重要作用。理解它的工作原理及正确的使用方法对实现高效且健壮的并发控制至关重要。

目录
相关文章
|
算法 Java
JAVA 关键字、敏感字 屏蔽过滤功能实现
JAVA 关键字、敏感字 屏蔽过滤功能实现
1360 0
JAVA 关键字、敏感字 屏蔽过滤功能实现
|
数据可视化 Java
探索Drools:Java世界的规则引擎
探索Drools:Java世界的规则引擎
809 1
|
Java Spring JSON
干货|Spring Cloud Bus 消息总线介绍
继上一篇 《干货|Spring Cloud Stream 体系及原理介绍》 之后,本期我们来了解下 Spring Cloud 体系中的另外一个组件 Spring Cloud Bus (建议先熟悉 Spring Cloud Stream,不然无法理解 Spring Cloud Bus 内部的代码)。
8248 0
|
10月前
|
数据采集 存储 供应链
数据合并:cbind函数在网页爬取中的实用技巧
本文介绍了如何通过代理IP和多线程技术提高网页爬取效率,并使用`cbind`函数合并数据。以财经网新闻为例,展示了从指定网站下载、解析内容,到数据获取、合并及分析的完整流程。通过亿牛云爬虫代理和Python代码实现,确保高效无痕访问,最终将结果保存为CSV文件。此方法适用于大量分散数据的爬取与处理,助力经济趋势分析。
308 47
|
IDE Java 开发工具
从零开始学Java Socket编程:客户端与服务器通信实战
【6月更文挑战第21天】Java Socket编程教程带你从零开始构建简单的客户端-服务器通信。安装JDK后,在命令行分别运行`SimpleServer`和`SimpleClient`。服务器监听端口,接收并回显客户端消息;客户端连接服务器,发送“Hello, Server!”并显示服务器响应。这是网络通信基础,为更复杂的网络应用打下基础。开始你的Socket编程之旅吧!
228 3
|
存储 缓存 安全
内存屏障,写屏障和读屏障
本文介绍了Java内存模型(JMM)的关键概念,包括主内存、工作内存、原子性操作、可见性和有序性,并详细解释了写屏障和读屏障的作用,它们是用来确保多线程环境中内存可见性和指令重排序一致性的同步操作。
347 1
|
存储 Java 开发者
HashMap线程安全问题大揭秘:ConcurrentHashMap、自定义同步,一文让你彻底解锁!
【8月更文挑战第24天】HashMap是Java集合框架中不可或缺的一部分,以其高效的键值对存储和快速访问能力广受开发者欢迎。本文深入探讨了HashMap在JDK 1.8后的底层结构——数组+链表+红黑树混合模式,这种设计既利用了数组的快速定位优势,又通过链表和红黑树有效解决了哈希冲突问题。数组作为基石,每个元素包含一个Node节点,通过next指针形成链表;当链表长度过长时,采用红黑树进行优化,显著提升性能。此外,还介绍了HashMap的扩容机制,确保即使在数据量增大时也能保持高效运作。通过示例代码展示如何使用HashMap进行基本操作,帮助理解其实现原理及应用场景。
221 1
|
监控 算法 Java
深入理解Java虚拟机:JVM调优与性能提升
本文旨在为Java开发者提供一条清晰的路径,以深入掌握Java虚拟机(JVM)的内部机制和性能调优技巧。通过具体案例分析,我们将探讨如何识别性能瓶颈、选择合适的工具进行监控与调试,以及实施有效的优化策略,最终达到提高应用程序性能的目的。文章不仅关注理论,更注重实践应用,帮助读者在面对复杂的Java应用时能够游刃有余。
207 0
|
人工智能
有效上下文提升20倍!DeepMind发布ReadAgent框架
【4月更文挑战第10天】DeepMind的ReadAgent框架解决了大型语言模型处理长文本的局限,模仿人类阅读策略,将长文分块并生成gist记忆。实验显示,ReadAgent在长篇文档理解任务上超越基线,有效上下文长度提升3至20倍。该方法无需特殊训练,但可能不适应所有类型长文本,且在极长文本中可能丢失细节,增加计算成本。
218 1
有效上下文提升20倍!DeepMind发布ReadAgent框架
|
SQL 数据可视化 前端开发
简单好用的ElasticSearch可视化工具:es-client和Head
使用 ElasticSearch(简称 es) 的过程中,经常有一些临时查询(如 排查问题、验证效果),一个趁手的可视化工具 可以提高工作效率。个人倾向于 免费(最好开源)、易于安装(如 浏览器插件),`es-client` 就是 比较简单好用的一个,尤其是 查询
11933 0