java 多线程-Semaphore信号量

说明

Semaphore 是 java.util.concurrent 包下的一个类

信号量是对锁的扩展,锁一次只允许一个线程访问资源,而信号量却可以 指定多个线程,同时访问某一个资源。

作用

  • 用于多个共享资源的互斥使用

  • 用于并发线程数量的控制

理解

  • 饭馆有 5 张饭桌 (多个共享资源)
  • 一个饭桌只能坐 1 人 (互斥使用的)
  • 来了 8 个人
  • 同时有 5 人吃饭 (并发线程数量的控制)
  • 其他 3 个需要等待
  • 当有人吃完离开后,才能进去一个吃饭

应用场景

项目中需要使用第三方提供的接口,如:发短信、校验身份证、人脸识别等

第三方供对接口有并发量限制,如:同时发短信,最大并发量不超过50,并发量超过50个不处理(相当于有50张饭桌,可以有成千上万人吃饭,但最多同时吃饭只有50桌)

此时可以使用 Semaphore 信号量

使用

  • acquire():从信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
    相当于获得一个饭桌(前提有空闲饭桌)

  • release():释放一个许可,将其返回给信号量。
    相当于吃完离开,饭桌空闲,可以给其他人使用

例子

自定义线程类

package 信号量;

import java.util.concurrent.Semaphore;

public class MyRun3 implements Runnable{
    /**
     * 信号量,最多同时有5人吃饭
     */
    Semaphore sem = new Semaphore(5);


    @Override
    public void run(){
        try {
            //获取信号量
            sem.acquire();
            String name = Thread.currentThread().getName();
            System.out.println(name + " 有人占用开始吃饭");
            Thread.sleep(3000);
            //释放信号量
            sem.release();
            System.out.println(name + " 吃完离开");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

启动类

package 信号量;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main3 {

    public static void main(String[] args) {
        MyRun3 myRun = new MyRun3();
        // 创建线程池,8个线程,相当于有 8个人
        ExecutorService executorService = Executors.newFixedThreadPool(8);

        for (int i = 0;i<8;i++){
            executorService.execute(myRun);
        }
        executorService.shutdown();
    }


}

执行结果:

参考:
https://www.cnblogs.com/songlove/p/15333552.html
https://baijiahao.baidu.com/s?id=1663727968804364989&wfr=spider&for=pc