引自:https://blog.csdn.net/Dason_yu/article/details/79734425
一、信号量
一个计数信号量。从概念上讲,信号量维护了一个许可集。Semaphore经常用于限制获取某种资源的线程数量。在java并发中,即Semaphore维护指定数量许可,当Semaphore中有额外(空闲)的许可时,线程获取到许可信号后(调用acquire()),线程才允许被执行,否则将被阻塞。当线程执行完毕,就会将占用的许可释放(调用release())。
此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证。当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。
二、用法
package com.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * 信号量一般用于用于限制获取某种资源的线程数量 * * @author Dason * */ public class SemaphoreTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); // 创建一个管理 3 个许可的信号量 final Semaphore sp = new Semaphore(3); for (int i = 0; i < 10; i++) { Runnable runnable = new Runnable() { public void run() { try { // 获取一个许可,若没有则被阻塞 sp.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } // availablePermits(): 返回此信号量中当前可用的许可数. System.out.println( "线程" + Thread.currentThread().getName() + "进入,当前已有" + (3 - sp.availablePermits()) + "个并发"); try { Thread.sleep((long) (Math.random() * 100)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "即将离开"); // 释放一个许可. sp.release(); // 下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元 System.out.println( "线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3 - sp.availablePermits()) + "个并发"); } }; service.execute(runnable); } } }