前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java多线程六脉神剑-少冲剑-Semaphore

Java多线程六脉神剑-少冲剑-Semaphore

原创
作者头像
BLACK595
发布2024-09-28 10:41:38
1210
发布2024-09-28 10:41:38

theme: smartblue


前言

少冲剑:少冲剑轻灵迅速,Semaphore 用于控制资源的访问数量,操作灵活迅速。

Semaphore(信号量):Semaphore用于控制线程的并发数量,规定一个公共资源同一时间能够多少线程访问。在Semphore初始化时指定“许可”数量,这个数量代表同一时间能够访问资源的线程数量,当一个线程调用acquire尝试获取许可时,如果获取成功,许可数量减一;当许可已分配完了,获取失败,线程阻塞等待,只有当其他线程调用release释放许可时,才有机会获取成功。

image.png
image.png

Semaphore常用方法详解

  • acquire:尝试获取一个许可,如果没有可用许可则阻塞等待,直到获取到许可或被中断。
  • acquire(int permits):尝试获取permits数量的许可,如果没有足够的许可则阻塞,直到获取到足够的许可或被中断。
  • tryAcquire():尝试获取一个许可,获取成功返回true,失败返回false,不会阻塞。
  • tryAcquire(int permits, long timeout, TimeUnit unit):尝试在指定时间内获取permits数量的许可,获取成功返回true,失败返回false,不会阻塞。
  • release():释放一个许可。
  • release(int permits): 释放permits数量许可。
  • availablePermits():返回当前可用许可数量。
  • drainPermits():将可用许可数量设置为0,并返回当前可用许可数量。
  • hasQueuedThreads():判断是否有线程正在等待获取许可。
  • getQueueLength():返回正在等待获取许可的线程数量。
  • isFair():判断该Semaphore是否是公平模式。公平模式下,等待时间最长的线程会优先获取许可;非公平模式则不一定。
  • getQueuedThreads():返回一个包含所有正在等待获取许可的线程的Collection。举个栗子🌰有10位客人到餐厅吃饭,但是餐厅只有5个位置,因此有5位客人需要根据来时的顺序,一位客人吃完后再进去一位。显然,Semaphore的许可证数量为餐厅位置数量5,需要根据先来先服务顺序(公平锁)为客人服务。

代码如下:

代码语言:java
复制
public class SemaphoreCase {
    public static void main(String[] args) {
        Runnable customer = new Runnable() {
            Semaphore availableTable = new Semaphore(5, true);
            int count = 1;
            @Override
            public void run() {
                int time = RandomUtil.randomInt(1, 10);
                int num = count++;
                try {
                    availableTable.acquire();
                    System.out.println("第【" + num + "】个用户正在用餐,需要时间:" + time + "s!");
                    Thread.sleep(time * 1000);
                    //释放锁
                    availableTable.release();
                    //判断是否有线程正在等待
                    if (availableTable.hasQueuedThreads()) {
                        System.out.println("第【" + num + "】个客户已用餐完毕,有请下一位!,目前有空闲桌位有【"+availableTable.availablePermits()+"】桌");
                    } else {
                        System.out.println("第【" + num + "】个客户已用餐完毕,目前有空闲桌位有【"+availableTable.availablePermits()+"】桌");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 1; i < 10; i++) {
            new Thread(customer).start();
        }
    }
}

执行结果:

代码语言:txt
复制
第【2】个用户正在用餐,需要时间:3s!
第【3】个用户正在用餐,需要时间:4s!
第【2】个用户正在用餐,需要时间:8s!
第【1】个用户正在用餐,需要时间:4s!
第【1】个用户正在用餐,需要时间:9s!
第【2】个客户已用餐完毕,有请下一位!,目前有空闲桌位有【1】桌
第【1】个用户正在用餐,需要时间:3s!
第【1】个客户已用餐完毕,有请下一位!,目前有空闲桌位有【1】桌
第【6】个用户正在用餐,需要时间:6s!
第【3】个客户已用餐完毕,有请下一位!,目前有空闲桌位有【1】桌
第【5】个用户正在用餐,需要时间:5s!
第【1】个客户已用餐完毕,有请下一位!,目前有空闲桌位有【1】桌
第【4】个用户正在用餐,需要时间:3s!
第【2】个客户已用餐完毕,目前有空闲桌位有【1】桌
第【1】个客户已用餐完毕,目前有空闲桌位有【3】桌
第【5】个客户已用餐完毕,目前有空闲桌位有【3】桌
第【4】个客户已用餐完毕,目前有空闲桌位有【4】桌
第【6】个客户已用餐完毕,目前有空闲桌位有【5】桌

应用实例

  1. 限制并发访问数量:有一些资源我们要限制并发访问的数量,例如数据库连接,如果过多连接同时访问数据库,数据库的压力会非常大,影响系统整体的性能。因此我们可以用Semaphore设置许可数量为10,限制最多10个连接同时访问。
  2. 资源复用:Semahore也常用于管理资源池,比如数据库连接池、线程池等。在资源池中,每个资源都与一个许可相对应。当一个线程想要使用某个资源(比如数据库连接池中获取一个数据库连接),他必须先从信号量那里获取到许可。例如,有一个数据库连接池有10个可用连接,当一个线程要使用数据库连接时,他必须要先获取一个许可,使用完之后必须将许可释放回信号量。如果没有信号量的控制,多个线程可能会无限制地创建新的数据库连接,导致数据库负载过高,甚至崩溃。信号量帮助我们有效管理和复用了资源,保证资源被合理、高效地使用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Semaphore常用方法详解
  • 应用实例
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档