信号量可用于限制并发线程的数量,并且实质上,此类维护一组许可。
acquire()
从信号量获取许可,然后release()
将许可返回信号量。 如果没有许可证,则acuire()
将阻塞直到可用
信号量用于控制对特定资源的访问。
工作流程
信号量设置为一个计数值。 然后线程尝试获取许可,如果计数为 0 或小于 0,则线程将被阻塞,并且它将等待下一个许可(如果有)。 这将一直保持下去,直到数量大于 0。如果是,则信号量将提供对线程资源的访问。 然后线程将释放许可,计数将增加 1。
构造器
Semaphore(int permits)
:使用给定数量的许可和不公平的公平设置创建一个信号量Semaphore(int permits, boolean fair)
:创建具有给定许可数量和给定公平性设置的信号量
主要方法
void acquire()
:从当前信号量获取许可,阻塞直到可用,否则线程被中断。void acquire(int permits)
:从当前信号量获取指定的许可数量,直到所有可用或线程中断为止一直阻塞。int availablePermites()
:返回当前信号量中可用的当前许可数量
要查看所有方法,请单击此处,您将被重定向到 Oracle 官方文档。
信号量可用于锁定对特定资源的访问。 每个线程都必须请求“权限”,因此需要在访问资源之前调用方法acquire()
。 当线程不再需要资源时,它必须调用release()
来释放锁。
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) throws Exception {
Semaphore semExample = new Semaphore(1);
System.out.println("Available permits: " + semExample.availablePermits());
semExample.release();
System.out.println("Available permits: " + semExample.availablePermits());
semExample.acquire();
System.out.println("Available permits: " + semExample.availablePermits());
semExample.acquire();
System.out.println("Available permits: " + semExample.availablePermits());
semExample.acquire();
System.out.println("Available permits: " + semExample.availablePermits());
}
}
输出
Available permits: 1
Available permits: 2
Available permits: 1
Available permits: 0
从上面的示例中可以看到,当您调用release()
时,您正在向Semaphore
实例添加许可。 当您调用acquire()
时,您正在删除permit()
。 如果没有许可证,而您打电话给获取,它将等待直到许可证被释放,因此在上例中将永远不会执行最后一个打印语句。
如果您有 1 个许可,然后又有一个acquire()
调用,紧接着是一个release()
调用,则称为锁。
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
Semaphore thread = new Semaphore(1);
public static void main(String args[]) {
final SemaphoreDemo test = new SemaphoreDemo();
new Thread(){
@Override
public void run(){
test.mutualExclusion();
}
}.start();
new Thread(){
@Override
public void run(){
test.mutualExclusion();
}
}.start();
}
private void mutualExclusion() {
try {
System.out.println(Thread.currentThread().getName() + " is waiting to acquire a permit.");
thread.acquire();
System.out.println("Permit has been acquired to " + Thread.currentThread().getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " is releasing the permit...");
thread.release();
System.out.println("Released.");
}
}
}
输出
Thread-0 is waiting to acquire a permit.
Permit has been acquired to Thread-0
Thread-1 is waiting to acquire a permit.
Thread-0 is releasing the permit...
Released.
Permit has been acquired to Thread-1
Thread-1 is releasing the permit...
Released.
从输出中可以看到,线程 0 允许了一个获取,线程 1 开始等待为其本身获取一个许可,但是它(线程 1)仅在线程 0 释放其许可时才获得它。