当前位置:首页 > Java > 正文

Java信号量详解(从零开始掌握Java并发控制中的信号量Semaphore)

在多线程编程中,我们经常需要控制对共享资源的访问。Java 提供了多种同步机制,其中 信号量(Semaphore) 是一种非常灵活且强大的工具。本教程将带你从零开始理解并使用 Java 中的信号量,即使你是编程小白,也能轻松上手!

什么是信号量(Semaphore)?

信号量是一种用于控制多个线程对共享资源访问数量的同步工具。你可以把它想象成一个“通行证发放机”:系统中有一定数量的通行证(许可),线程必须先获取一个通行证才能执行关键代码;用完后归还通行证,其他线程才能使用。

Java信号量详解(从零开始掌握Java并发控制中的信号量Semaphore) Java信号量 信号量使用教程 Java并发控制 信号量Semaphore 第1张

Java信号量的基本用法

在 Java 中,java.util.concurrent.Semaphore 类提供了信号量的实现。创建信号量时,你需要指定初始的许可数量。

1. 创建信号量

// 创建一个拥有3个许可的信号量Semaphore semaphore = new Semaphore(3);

2. 获取和释放许可

线程通过 acquire() 方法获取许可,通过 release() 方法释放许可。

try {    semaphore.acquire(); // 获取一个许可,若无可用则阻塞等待    // 执行需要控制并发的代码} finally {    semaphore.release(); // 释放许可,一定要放在 finally 块中确保释放}

完整示例:模拟停车场场景

假设一个停车场最多只能停3辆车。当停车场满员时,新来的车必须等待有车离开后才能进入。我们可以用信号量来模拟这个过程。

import java.util.concurrent.Semaphore;public class ParkingExample {    // 停车场最多容纳3辆车    private static final Semaphore parkingSpaces = new Semaphore(3);    public static void main(String[] args) {        // 模拟10辆车尝试进入停车场        for (int i = 1; i <= 10; i++) {            new Thread(new Car(i)).start();        }    }    static class Car implements Runnable {        private int carId;        public Car(int carId) {            this.carId = carId;        }        @Override        public void run() {            try {                System.out.println("汽车 " + carId + " 正在等待进入停车场...");                parkingSpaces.acquire(); // 获取停车位                System.out.println("汽车 " + carId + " 已进入停车场。");                Thread.sleep(2000); // 停留2秒                System.out.println("汽车 " + carId + " 离开停车场。");            } catch (InterruptedException e) {                Thread.currentThread().interrupt();            } finally {                parkingSpaces.release(); // 释放停车位            }        }    }}

运行这段代码,你会看到最多只有3辆汽车同时在“停车场”内,其余车辆会排队等待。这正是 Java信号量 控制并发访问数量的典型应用。

信号量的其他常用方法

  • acquire(int permits):一次获取多个许可。
  • release(int permits):一次释放多个许可。
  • tryAcquire():尝试获取许可,如果无法立即获取则返回 false,不会阻塞。
  • availablePermits():返回当前可用的许可数量。

使用信号量的注意事项

1. 务必在 finally 块中释放许可,防止因异常导致许可未被释放,造成死锁。

2. 信号量是非重入的,同一个线程多次调用 acquire() 会消耗多个许可。

3. 信号量常用于实现资源池(如数据库连接池)、限流等场景。

总结

通过本教程,你已经掌握了 Java信号量 的基本概念、使用方法和实际应用场景。信号量是 Java 并发编程中不可或缺的工具之一,合理使用它可以有效控制资源访问,避免系统过载。

记住我们的四个核心关键词:Java信号量信号量使用教程Java并发控制信号量Semaphore。希望你能将所学知识应用到实际项目中,写出更安全、高效的多线程程序!