前言:本文将简单介绍一下Semaphore的基本概念已经如何通过Semaphore实现资源限流的操作

一,什么是Semaphore?

举个通俗点的栗子,Semaphore就好比一个公共停车场,停车场的最大车位也就是资源的限制。

Semaphore的核心作用就是实现资源限流

基本原理

Semaphore可以实现对公共资源的使用限制,既然是使用资源,那自然就有获取资源以及释放资源操作。就好比内存的申请与释放,加锁与解锁一致。不过Semaphore获取资源需要通过两个关键的方法来实现:
Semaphore维护了一些固定的资源(就好比停车常固定车位)

  • 获取资源:通过acquire()来获取,此时会分为两种情况。
    • 1)能拿到,那就进去停车,畅通无阻
    • 2)拿不到,没车位了,那就只能阻塞等待,直到有人把车位让出来
  • 释放资源:通过release()完成释放,就好比让出车位,此时就会唤醒外面由于没车位停车而等待的车辆(或者说是线程)

Semaphore的主要使用其实还是在多线程中,如果把车辆比作线程,那就可以限制线程之间的最大开销量,避免资源泄露的情况发送。

Semaphore和锁的区别

如果把普通的排他锁(比如 synchronizedReentrantLock)比作“单人更衣室”,一次只能进一个人;那么 Semaphore 就是一个“允许多人同时使用的公共资源”,

二,常用方法

  • new Semaphore(int permits):构造方法,设定初始的可用许可数量。

  • new Semaphore(int permits, boolean fair):第二个参数可以指定是否为“公平模式”。公平模式下,排队等待的线程会严格按照“先来后到”的顺序获取许可;非公平模式下(默认),线程可以尝试“插队”,这种模式虽然不讲武德,但系统的整体吞吐量会更高。

  • acquire():获取一个许可。拿不到就死等,会响应线程中断机制。

  • tryAcquire():尝试获取许可,拿到返回 true,拿不到立刻返回 false,不会让线程干等。

  • release():释放一个许可。注意:在实际开发中,这个方法一定要放在 finally 代码块中,确保即使业务代码抛出异常,许可也能被正确归还。

三,代码案例

假设后端服务有一个非常消耗资源的接口,为了防止服务器被压垮,我们需要限制最多只能有 3 个线程同时处理请求:

public class SemaphoreDemo {  
    public static void main(String[] args) {  
        // 创建一个具有 3 个许可的信号量(停车场只有 3 个车位)  
        Semaphore semaphore = new Semaphore(3);  
  
        // 模拟 6 个用户的并发请求  
        ExecutorService threadPool = Executors.newFixedThreadPool(6);  
  
        for (int i = 1; i <= 6; i++) {  
            int threadId = i;  
            threadPool.execute(() -> {  
                try {  
                    // 1. 尝试进场,获取许可  
                    semaphore.acquire();  
                    System.out.println("线程 " + threadId + " 拿到许可,开始处理业务...");  
  
                    // 模拟业务处理耗时 2 秒  
                    Thread.sleep(2000);  
  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                } finally {  
                    // 2. 业务处理完毕,释放许可  
                    System.out.println("线程 " + threadId + " 执行完毕,释放许可。");  
                    semaphore.release();  
                }  
            });  
        }  
        threadPool.shutdown();  
    }  
}

运行显示:
image.png

以上就是有关Semaphore的简单认识,并不是很难,如有纰漏还请指出~~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐