一:认识Seamphore
Seamphore信号量主要用来控制同时访问特定资源的线程数量,我们可以把它理解成用来限流用的。
其主要方法如下:
acquire(),获得许可,如果没获取到,会一直等待。
acquire(int permits):获得permits个许可。
tryAcquire(),尝试获得许可。
release():释放许可。
Collection<Thread> getQueuedThreads():返回所有等待获取许可的线程集合。
boolean hasQueuedThreads():是否有线程在等待获取许可。
int availablePermits():返回当前可以的许可证的数量。
int getQueueLength():返回正在等待获取许可的线程数量。
二:举例说明
模拟8个线程同时访问某个资源,采用Seamphore来控制并发访问量
- public class SemaphoreExample {
- public static void main(String[] args) {
- ExecutorService service = Executors.newFixedThreadPool(10);
- final Semaphore semaphore = new Semaphore(5);
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- for (int i = 1; i <= 8; i++) {
- final int index = i;
- service.submit(new Runnable() {
- @Override
- public void run() {
- try {
- semaphore.acquire();
- System.out.println("获得许可:"
- + Thread.currentThread().getName());
- //不释放锁,模拟操作
- Thread.sleep(1000);
- System.out.println("释放许可:"
- + Thread.currentThread().getName());
- semaphore.release();
- System.out.println("当前允许进入的最大任务数:" + semaphore.availablePermits());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally{
- if(index == 8){
- countDownLatch.countDown();
- }
- }
- }
- });
- }
- try {
- System.out.println("main线程等待:" + Thread.currentThread().getName());
- countDownLatch.await();
- System.out.println("模拟执行完毕.....");
- service.shutdown();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
可能得运行结果如下:
- 获得许可:pool-1-thread-1
- 获得许可:pool-1-thread-3
- 获得许可:pool-1-thread-2
- 获得许可:pool-1-thread-4
- 获得许可:pool-1-thread-5
- main线程等待:main
- 释放许可:pool-1-thread-1
- 当前允许进入的最大任务数:1
- 获得许可:pool-1-thread-6
- 释放许可:pool-1-thread-5
- 释放许可:pool-1-thread-2
- 当前允许进入的最大任务数:2
- 获得许可:pool-1-thread-7
- 释放许可:pool-1-thread-3
- 当前允许进入的最大任务数:1
- 获得许可:pool-1-thread-8
- 当前允许进入的最大任务数:2
- 释放许可:pool-1-thread-4
- 当前允许进入的最大任务数:2
- 释放许可:pool-1-thread-6
- 当前允许进入的最大任务数:3
- 释放许可:pool-1-thread-7
- 当前允许进入的最大任务数:4
- 释放许可:pool-1-thread-8
- 当前允许进入的最大任务数:5
- 模拟执行完毕.....
可以看到,每次最多5个线程并发执行,后面的线程必须等待。