可以控制系统的流量: 拿到信号量的线程可以进入, 否则等待. 通过acquire()和release()获取和释放访问许可 (进入方法体时候获取许可 离开方法体是释放许可)
Semaphore可以维护当前访问自身的线程个数, 并提供了同步机制. 使用Semaphore可以控制同时访问资源的线程个数, 例如实现一个文件允许的并发访问数
Semaphore实现的功能就类似厕所有5个坑, 假如有设个人要上厕所, 那么同时能有多少个人去上厕所呢? 同时只能有5个人能够占用, 当5个人中的任何一个人离开后, 其中在等待的另外五个人中又有一个可以占用了. 另外等待的5个人中可以使随机获得优先机会, 也可以是按照先来后到的顺序获得机会, 这取决于构造Semaphore对象时传入的参数选项
单个信号量的Semaphore对象可以实现互斥锁的功能, 并且可以是由一个线程获得了"锁", 再由另一个线程释放"锁", 者可应用于死锁恢复的一些场合
代码
package mutithread.semaphore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
// 创建线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 创建信号量并设置个数
final Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
Runnable runnable = () -> {
// 使用 1.8 练练手
// 线程进来后先得到信号量
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + //
"进入, 当前已有" + (3 - semaphore.availablePermits()) + "个并发");
try {
Thread.sleep((long) Math.random());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "即将离开");
// 释放信号量
semaphore.release();
};
executorService.execute(runnable);
}
executorService.shutdown();
}
}