【java.util.concurrent】Semaphore详解

概念:java

一个计数信号量,信号量维护了一个许可集。Semaphore 只对可用许可的号码进行计数,并采起相应的行动。拿到信号量的线程能够进入代码,不然就等待。经过acquire()和release()获取和释放访问许可。ide

  • acquire():获取从这个信号量许可证,阻塞直到有一个可用,或线程被中断。
  • release() :释放一个许可,将可用的许可数增长 1。若是任意线程试图获取许可,则选中一个线程并将刚刚释放的许可给予它。

验证示例:ui

public class SemaphoreTest {
	private static int MAX_VALUE = 5;
	private static List<Integer> list = new LinkedList<Integer>();
	private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();
	
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		/* Semaphore能够控制某个资源可被同时访问的个数
		 * 
		 * Semaphore(int permits)
		 * Semaphore(int permits, boolean fair)
		 *
		 * permits 初始许可数,也就是最大访问线程数
		 * fair 当设置为false时,线程获取许可的顺序是无序的,也就是说新线程可能会比等待的老线程会先得到许可;
		 * 当设置为true时,信号量保证它们调用的顺序(即先进先出;FIFO)
		 */
		Semaphore semaphore = new Semaphore(MAX_VALUE, true);
		ExecutorService es = Executors.newCachedThreadPool();//Executor接口拥有execute方法,ExecutorService继承Executor
		for(int i=0; i<4*MAX_VALUE; i++){
			//内部类访问成员变量,若局部变量不修改的状况下能够省去final关键字,since1.8;若改变,编译器将提示局部变量必须为final类型
			final int index = i;
			es.execute(new PRunnable(semaphore, index));
		}
		Thread.sleep(300);
		//退出线程池
		es.shutdown();
		System.out.println("最后还有"+semaphore.availablePermits()+"个许可可用");
	}
}

class PRunnable implements Runnable{
	private final Semaphore semaphore;
	private int index;
	
	public PRunnable(Semaphore semaphore, int index){
		this.semaphore = semaphore;
		this.index = index;
	}
	
	public void getAcquire(){
		System.out.println(index+"号车进入");
	}
	
	public void releaseAcquire(){
		System.out.println(index+"号车离开");
	}
	
	@Override
	public void run() {
		try {
			//acquire() 获取从这个信号量许可证,阻塞直到有一个可用,或线程被中断。
			semaphore.acquire();
			getAcquire();
			//release() 释放一个许可,将可用的许可数增长 1。若是任意线程试图获取许可,则选中一个线程并将刚刚释放的许可给予它。
			semaphore.release();
			releaseAcquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 若是屏蔽semaphore.release()语句,则在控制台只能打印 MAX_VALUE 条记录,以后线程一直阻塞。this

相关文章
相关标签/搜索