项目经验
接下来,咱们使用代码的方式来演示 Semaphore 的使用。我们以停车场的限流为例,假设整个停车场只有 2 个车位(车位虽少,但足矣说明问题),但来停车的却有 5 辆车,显然车位不够用了,此时需要保证停车场最多只能有 2 辆车,接下来咱们使用 Semaphore 来实现车辆的限流功能,具体实现代码如下:
import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * Author:磊哥 * By:Java中文社群 */ publicclass SemaphoreExample { // 创建信号量 static Semaphore semaphore = new Semaphore(2); public static void main(String[] args) { // 创建 5 个固定的线程数 ExecutorService threadPool = Executors.newFixedThreadPool(5); // 定义执行任务 Runnable runnable = new Runnable() { @Override public void run() { // 拿到当前线程的名称 String tname = Thread.currentThread().getName(); System.out.println(String.format("老司机:%s,停车场外排队,时间:%s", tname, new Date())); try { // 执行此行,让所有线程先排队等待进入停车场 Thread.sleep(100); // 执行阻塞 semaphore.acquire(); System.out.println(String.format("老司机:%s,已进入停车场,时间:%s", tname, new Date())); Thread.sleep(1000); System.out.println(String.format("老司机:%s,离开停车场,时间:%s", tname, new Date())); // 释放锁 semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }; // 执行任务 1 threadPool.submit(runnable); // 执行任务 2 threadPool.submit(runnable); // 执行任务 3 threadPool.submit(runnable); // 执行任务 4 threadPool.submit(runnable); // 执行任务 5 threadPool.submit(runnable); // 等线程池任务执行完之后关闭 threadPool.shutdown(); } }
以上代码的执行结果如下:
从上述的结果我们可以看出,当有 5 辆车同时需要进入停车场时,因为停车场的停车位只有 2 个,所以停车场最多只能容纳 2 辆车。此时我们通过 Semaphore 的 acquire 方法(阻塞等待)和 release 方法(颁发一个证书)顺利的实现了限流的功能,让停车场的车辆数始终控制在 2 辆车以下(等于或小于 2 辆车)。