并发编程【Semaphore】
一、使用场景
Semaphore 翻译成字面意思为 信号量,Semaphore 可以控制同时访问的线程个数。
通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
信号量主要用于两个目的:
- 用于多个共享资源的互斥使用;
- 用于并发线程数的控制。
二、代码实现
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for(int i=1; i<=6; i++){
new Thread(()->{
try {
// 获取资源
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "抢占到了车位");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放资源
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
运行结果:
1抢占到了车位
3抢占到了车位
2抢占到了车位
2离开了车位
3离开了车位
1离开了车位
4抢占到了车位
6抢占到了车位
5抢占到了车位
6离开了车位
4离开了车位
5离开了车位
三、大致原理分析
acquire() :当一个线程调用acquire操作时,它要么成功获取信号量(同时信号量减1),要么一直等下去,直到有线程释放信号量,或超时。
release():实际上会将信号量的值加1,然后唤醒等待的线程。
四、特殊使用
当使用Semaphore semaphore = new Semaphore(1);
代码创建建信号量时,实际上就相当于使用 synchronized 进行加锁。
五、其它 API 方法
// 用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可
public void acquire()
// 获取 permits 个许可
public void acquire(int permits)
// 释放许可。注意,在释放许可之前,必须先获获得许可
public void release()
// 释放 permits 个许可
public void release(int permits)
上面 4 个方法都会被阻塞,如果想立即得到执行结果,可以使用下面几个方法:
// 尝试获取一个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
public boolean tryAcquire():
// 尝试获取一个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false
public boolean tryAcquire(long timeout, TimeUnit unit)
// 尝试获取 permits 个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
public boolean tryAcquire(int permits):
// 尝试获取 permits个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false
public boolean tryAcquire(int permits, long timeout, TimeUnit unit):
// 得到可用的许可数目
public int availablePermits()
Java新手,若有错误,欢迎指正!