Java信号量示例
信号量可以用来限制并发线程的数量,实际上,这个类维护一组许可证。
acquire()从信号量获取许可证,release()将许可证返回给信号量。如果没有许可证,acuire()将阻塞,直到有一个许可证可用
信号量用于控制对特定资源的访问。
工作流程
用计数值设置信号量。然后线程尝试获取permit,如果计数为0或者小于0,则线程将被阻塞并等待下一个许可(如果有)。此操作将一直进行,直到计数大于0。如果是,信号量将提供对线程资源的访问。线程将释放许可证,计数将增加1.
构造函数
Semaphore(int permits): 使用给定的许可数量和非公平性设置创建一个信号量
Semaphore(int permits, boolean fair):创建一个具有给定许可数量和给定公平性设置的信号量
主要方法
void acquire():从当前信号量获取许可,阻塞直到有一个可用,或者线程被中断。
voidacquire(intpermits):从当前信号量获取指定的许可数,阻塞直到所有许可证可用或者线程中断。
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()时,我们正在向信号量实例添加一个许可证。调用acquire()时,将删除permit()。当没有许可证而我们调用acquire时,它将等待直到许可证被释放,因此在上面的示例中,最后一个print语句永远不会执行。
当你有1个permit,然后你有一个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.
从Thread-0允许获取后的输出中可以看到,线程1开始等待为自己获取许可,但它(Thread-1)只在Thread-0释放它的许可时才获得许可。