定义解释:
一个计数信号量。在概念上,信号量维持一组许可证。如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它。每个release()添加许可证,潜在地释放阻塞获取方。但是,没有使用实际的许可证对象;Semaphore只保留可用数量的计数,并相应地执行。
构造方法:
| Constructor and Description |
|---|
| Semaphore(int permits) 创建一个 Semaphore与给定数量的许可证和非公平公平设置。 |
| Semaphore(int permits, boolean fair) 创建一个 Semaphore与给定数量的许可证和给定的公平设置。 |
| Modifier and Type | Method and Description |
|---|---|
| void | acquire() 从该信号量获取许可证,阻止直到可用,或线程为 interrupted 。 |
| void | acquire(int permits) 从该信号量获取给定数量的许可证,阻止直到所有可用,否则线程为 interrupted 。 |
| void | acquireUninterruptibly() 从这个信号灯获取许可证,阻止一个可用的。 |
| void | acquireUninterruptibly(int permits) 从该信号量获取给定数量的许可证,阻止直到所有可用。 |
| int | availablePermits() 返回此信号量中当前可用的许可数。 |
| int | drainPermits() 获取并返回所有可立即获得的许可证。 |
| protected Collection | getQueuedThreads() 返回一个包含可能正在等待获取的线程的集合。 |
| int | getQueueLength() 返回等待获取的线程数的估计。 |
| boolean | hasQueuedThreads() 查询任何线程是否等待获取。 |
| boolean | isFair() 如果此信号量的公平设置为真,则返回 true 。 |
| protected void | reducePermits(int reduction) 缩小可用许可证的数量。 |
| void | release() 释放许可证,将其返回到信号量。 |
| void | release(int permits) 释放给定数量的许可证,将其返回到信号量。 |
| String | toString() 返回一个标识此信号量的字符串及其状态。 |
| boolean | tryAcquire() 从这个信号量获得许可证,只有在调用时可以使用该许可证。 |
| boolean | tryAcquire(int permits) 从这个信号量获取给定数量的许可证,只有在调用时全部可用。 |
| boolean | tryAcquire(int permits, long timeout, TimeUnit unit) 从该信号量获取给定数量的许可证,如果在给定的等待时间内全部可用,并且当前线程尚未 interrupted 。 |
| boolean | tryAcquire(long timeout, TimeUnit unit) 如果在给定的等待时间内可用,并且当前线程尚未 到达 interrupted,则从该信号量获取许可。 |
代码示范:打疫苗
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(2);
//打完针离开了房间
System.out.println(Thread.currentThread().getName()+":离开房间");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//释放可以执行的信号
}
},String.valueOf(i)).start();
}
}
以上代码很简单,主要为了方便记住该类是做什么的,有什么用。
最后切记一点:
单元测试中使用 TimeUnit.SECONDS.sleep(3);
一定要在外面主线程中进行等待,否则,主线程执行完单元测试内的线程没执行完,那就真完了。
三种方法:
1.加上Thread.join()
2.CountDownLetch()
3.外面也加上睡眠时间,时长要大 如:
@Test
public void time01(){
new Thread(()->{
System.out.println("开始:");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("过了两秒:");
}).start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
完结撒花,如有不对,请评判指正



