跳至主要內容

Semaphore

chanchaw大约 2 分钟languagejava

概述

概念

Semaphore 是一个计数信号量(一般开发中称作信号量),在JDK1.5中引入的一个并发工具类,位于 java.util.concurrent 包中。其用来控制同时访问资源的线程的个数。

工作原理

Semaphore 计数信号量由一个指定数量的“许可”初始化。每调用一次 acquire 方法一个许可会被调用线程取走。每调用一次 release 方法一个许可会被返还给信号量。因此在没有任何 release 调用时,最多允许N个线程通过 acquire 方法,N是该信号量初始化时的许可的指定数量。

常用方法

下面所有方法都是 Semaphore 中的 public 方法

Semaphore(int permits)

创建一个信号量,permits 是许可证的数量

Semaphore(int permits,boolean fair)

第二个参数 fair 表示公平的,即多个线程争抢许可证时先到先得

void acquire()

阻塞请求一个许可证

void acquire(int permits)

阻塞请求多个许可证

void release()

阻塞释放许可证

void release(int permits)

阻塞释放多个许可证

boolean tryAcquire()

非阻塞,尝试获取一个许可证,成功的返回 true 相反则返回 false

boolean tryAcquire(long timeout,TimeUnit unit)

非阻塞,在超时时间 timeout 内获取到许可证则立即返回 true,超时仍然没有获取到则返回 false.

boolean tryAcquire(int permits)

非阻塞,获取多个许可证

boolean tryAcquire(int permits,long timeout,TimeUnit unit)

非阻塞,带有超时的获取多个许可证

int availablePermist()

获取信号量中当前有多少可用许可证

案例

代码

创建 springboot 项目,记得带有 lombok

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n</Pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

继承 Thread 的模拟停车场入场、出场类

package com.cc.semaphore.utils;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Semaphore;

@Slf4j
public class ParkingSpace extends Thread {
    private int carIndex;
    private Semaphore semaphore;

    public ParkingSpace(Semaphore semaphore, int carIndex) {
        this.carIndex = carIndex;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            log.info("[Index" + carIndex + "] acquire!");
            sleep(2000);// 睡眠2秒
            semaphore.release();
            log.info("[Index" + carIndex + "] release...");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

测试代码

package com.cc.semaphore.utils;

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Semaphore;

@Slf4j
public class TestSemaphore {
    private static final int VOLUME = 5;

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(VOLUME);
        for (int i = 0; i < 9; i++) {
            new ParkingSpace(semaphore,i).start();
        }
    }
}

仓库

仓库 https://gitee.com/chanchaw/JavaDemoCompopen in new window 中的模块 semaphore