前言
Semaphore当前在多线程环境下被广泛使用,信号量是个很重要的概念,在进程控制方面都有应用。Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。
构造方法
Semaphore类位于java.util.concurrent包下,它提供了2个构造器:
//参数permits表示许可数目,即同时可以允许多少线程进行访问 public Semaphore(int permits) { sync = new NonfairSync(permits); } //这个多了一个参数fair表示是否是公平的,即等待时间越久的越先获取许可 public Semaphore(int permits, boolean fair) { sync = (fair)? new FairSync(permits) : new NonfairSync(permits); }
常用方法
重要的几个方法,首先是acquire()、release()方法:
public void acquire() throws InterruptedException { } //获取一个许可 public void acquire(int permits) throws InterruptedException { } //获取permits个许可 public void release() { } //释放一个许可 public void release(int permits) { } //释放permits个许可
acquire()用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可。
release()用来释放许可。注意,在释放许可之前,要保证先获得许可。否则会导致总的许可数目就会错误
如果想立即得到执行结果,可以使用下面几个方法:
public boolean tryAcquire() { }; //尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { }; //尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false public boolean tryAcquire(int permits) { }; //尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回false public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { }; //尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false
public int availablePermits(); // 返回此信号量中可用的许可证的当前数量。
代码实践
通过例子了解Semaphore的具体使用:
停车场有五个车位,有十辆车需要进入停车场停车,此时需要保证停车场最多的时候只能有五辆车进入,出去一辆才能进来一辆
代码实现:
public static void main(String[] args) { // 停车场车位数量 Semaphore semaphore = new Semaphore(5); for (int i = 1; i <= 10; i++) { Thread thread = new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "进入停车场"); TimeUnit.SECONDS.sleep(new Random().nextInt(10)); System.out.println(Thread.currentThread().getName() + "驶离停车场"); } catch (InterruptedException e) { throw new RuntimeException(e); }finally { semaphore.release(); } }, i + "号车"); thread.start(); } }
运行结果:
1号车进入停车场 4号车进入停车场 3号车进入停车场 2号车进入停车场 5号车进入停车场 1号车驶离停车场 7号车进入停车场 4号车驶离停车场 6号车进入停车场 5号车驶离停车场 8号车进入停车场 3号车驶离停车场 9号车进入停车场 9号车驶离停车场 10号车进入停车场 2号车驶离停车场 6号车驶离停车场 7号车驶离停车场 8号车驶离停车场 10号车驶离停车场 Process finished with exit code 0
Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。