Semaphore是常见的同步工具类之一。
Semaphore翻译成字面意思为 信号量,Semaphore可以控制同时访问的线程个数,也称为permit(许可)。
在构造函数中指定permits个数。
/** * Creates a {@code Semaphore} with the given number of * permits and nonfair fairness setting. * * @param permits the initial number of permits available. * This value may be negative, in which case releases * must occur before any acquires will be granted. */ public Semaphore(int permits) { sync = new NonfairSync(permits); }
可以通过 acquire()方法 获取一个许可,Semephore可用的许可数量减一,如果没有可用的许可就阻塞。
使用acquire()方法需要捕捉InterruptedException异常。
而 release() 方法则会释放一个许可,将它返还给Semaphore,Semephore可用的许可数量加一。
即使没有调用过acquire()方法,也可以直接使用release()。
Semephore中的内部类NofairSync和FairSync继承了AQS (AbstractQueuedSynchronizer)。
Semephore的应用, 示例如下:
假设8个工人,轮流利用5台机器进行工作。那么信号量Semephore的许可permit初始化为5,每当有一个工人占用某一机器时,也就是acquire()时,permits减一。
当所有机器都在使用时,剩下的工人需要等待。
public class SemaphoreDemo { private static Semaphore semaphore=new Semaphore(5); public static void main(String[] args) { for(int i=0;i<8;i++) { new Thread (new Worker(i)) .start(); } } static class Worker implements Runnable { private int number; public Worker(int number) { this.number=number; } @Override public void run() { try { semaphore.acquire(); System.out.println("工人"+number+"正在使用某一台机器"); Thread.sleep(5*1000); semaphore.release(); System.out.println("---------------->工人"+number+"停止使用某一台机器"); }catch (InterruptedException e) { e.printStackTrace(); } } } }
运行结果如下:
工人0正在使用某一台机器 工人1正在使用某一台机器 工人2正在使用某一台机器 工人4正在使用某一台机器 工人5正在使用某一台机器 ---------------->工人4停止使用某一台机器 工人7正在使用某一台机器 ---------------->工人2停止使用某一台机器 工人3正在使用某一台机器 工人6正在使用某一台机器 ---------------->工人0停止使用某一台机器 ---------------->工人1停止使用某一台机器 ---------------->工人5停止使用某一台机器 ---------------->工人7停止使用某一台机器 ---------------->工人6停止使用某一台机器 ---------------->工人3停止使用某一台机器