Semaphore(信号量)了解吗?

Semaphore(信号量)用于控制同时访问特定资源的线程数量,它通过协调各个线程,以确保公共资源的合理使用。

为了更好地理解,我们可以举个停车场的例子。在现实生活中,停车位是有限的,只能容纳一定数量的车辆。当停车场还有空位时,指示牌会显示绿灯和剩余车位数量,车辆可以进入停车场。但是,如果停车位已满,指示牌会显示绿灯和数字0,车辆需要等待。当有车辆离开停车场时,指示牌会再次显示绿灯和可用的车位数量,等待的车辆可以进入停车场。

将这个例子与编程中的情况类比,车辆可以看作是线程,进入停车场代表线程正在执行,离开停车场代表线程执行完毕。红灯表示线程被阻塞,无法执行。Semaphore的本质就是协调多个线程对共享资源的获取。

除了停车场的例子,Semaphore还可以用于流量控制,特别是在公共资源有限的应用场景中,比如数据库连接。

假设我们有一个需求,需要读取数万个文件的数据。由于这是IO密集型任务,我们可以启动几十个线程并发读取。但是,如果读取到内存后还需要将数据存储到数据库中,而数据库的连接数只有10个,我们必须控制只有10个线程同时获取数据库连接来保存数据,否则会出现无法获取数据库连接的错误。这种情况下,可以使用Semaphore来实现流量控制,如下:

public class SemaphoreTest {
    private static final int THREAD_COUNT = 30;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
    private static Semaphore s = new Semaphore(10);

    public static void main(String[] args) {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        s.acquire();
                        System.out.println("save data");
                        s.release();
                    } catch (InterruptedException e) {
                    }
                }
            });
        }
        threadPool.shutdown();
    }
}

在代码中,虽然有30个线程在执行,但是只允许10个并发执行。Semaphore的构造方法 Semaphore(int permits)接受一个整型的数字,表示可用的许可证数量。Semaphore(10)表示允许10个线程获取许可证,也就是最大并发数是10。Semaphore的用法也很简单,首先线程使用 Semaphore的acquire()方法获取一个许可证,使用完之后调用release()方法归还许可证。还可以用tryAcquire()方法尝试获取许可证。

标签: java, Java面试题, Java问题合集, Java编程, Java问题精选, Java常见问题