什么是Semaphore

Semaphore是Java中的一个线程同步工具,用于控制访问特定资源的线程数。它主要用于解决并发访问资源时的线程安全问题。Semaphore维护了一个内部计数器,该计数器表示可以同时访问某个资源的线程数。

使用Semaphore

Semaphore的使用分为两个主要步骤:初始化和获取/释放许可。

1. 初始化Semaphore:可以通过构造函数来初始化Semaphore,指定允许的线程数量。例如,要初始化一个允许同时访问3个资源的Semaphore,可以使用new Semaphore(3)

2. 获取/释放许可:线程需要访问资源时,首先要通过acquire()方法获取一个许可(如果没有许可可用,则线程将被阻塞),然后执行相应的操作。完成后,需要通过release()方法释放许可,以便其他线程可以获取许可并访问资源。

示例代码


import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); // 初始化Semaphore,允许同时访问3个资源
        
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Worker(semaphore, i));
            thread.start();
        }
    }
}

class Worker implements Runnable {
    Semaphore semaphore;
    int id;
    
    public Worker(Semaphore semaphore, int id) {
        this.semaphore = semaphore;
        this.id = id;
    }
    
    @Override
    public void run() {
        try {
            semaphore.acquire();  // 获取许可
            System.out.println("Worker " + id + "正在访问资源");
            
            // 模拟访问资源
            Thread.sleep(2000);
            
            System.out.println("Worker " + id + "释放许可");
            semaphore.release();  // 释放许可
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上述示例中,通过new Semaphore(3)初始化了一个允许同时访问3个资源的Semaphore。然后创建5个Worker线程,每个线程都试图通过semaphore.acquire()获取许可并访问资源,然后执行一段耗时的操作。完成后调用semaphore.release()释放许可,以便其他线程可以获取许可并访问资源。

运行上述示例,你会发现只有3个线程可以同时访问资源,而其他线程需要等待某个线程释放许可后才能获取许可。这样就保证了同时访问资源的线程数量不会超过指定的数量。