Semaphore的作用:限制线程并发的数量
位于 java.util.concurrent 下,
构造方法
// 构造函数 代表同一时间,最多允许permits执行acquire() 和release() 之间的代码。 public Semaphore(int permits) { sync = new NonfairSync(permits); } //False:表示非公平信号量,即线程启动的顺序与调用semaphore.acquire() 的顺序无关,也就是线程先启动了并不代表先获得 许可 //True:公平信号量,即线程启动的顺序与调用semaphore.acquire() 的顺序有关,也就是先启动的线程优先获得许可 public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); }
- 方法acquire(n) 的功能是每调用1次此方法,就消耗掉n个许可。
- 方法release(n) 的功能是每调用1次此方法,就动态添加n个许可。
- 方法acquireUnnterruptibly()作用是是等待进入acquire() 方法的线程不允许被中断。
- 方法availablePermits() 返回Semaphore对象中当前可以用的许可数。
- 方法drainPermits() 获取并返回所有的许可个数,并且将可用的许可重置为0
- 方法 getQueueLength() 的作用是取得等待的许可的线程个数
- 方法 hasQueueThreads() 的作用是判断有没有线程在等待这个许可
- 方法tryAcquire() 的作用是尝试获取1个许可。如果获取不到则返回false,通常与if语句结合使用,其具有无阻塞的特点。无阻塞的特点可以使不至于在同步处于一直持续等待的状态。
- 方法tryAcquire(n) 的作用是尝试获取n个许可,如果获取不到则返回false
- 方法tryAcquire(long timeout,TimeUnit unit)的作用是在指定的时间内尝试获取1个许可,如果获取不到则返回false
- 方法tryAcquire(int permits,long timeout,TimeUnit unit) 的作用是在指定的时间内尝试获取n 个许可,如果获取不到则返回false
使用:
多进路-多处理-多出路:允许多个线程同时处理任务
private static Semaphore semaphore = new Semaphore(4); public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(new Runnable(){ @Override public void run(){ System.out.println(Thread.currentThread().getName()+" 正在运行"); try { semaphore.acquire();// //请求获得许可,如果有可获得的许可则继续往下执行,许可数减1。否则进入阻塞状态 System.out.println(Thread.currentThread().getName() + "进入,并发数:" + (4-semaphore.availablePermits())); Thread.sleep(3000); System.out.println(Thread.currentThread().getName() +"即将离开,并发数:" + (4-semaphore.availablePermits())); semaphore.release();//释放许可,许可数加1 }catch( Exception e){ e.printStackTrace(); } finally { } } }).start(); } }
运行结果:
Thread-1 正在运行 Thread-6 正在运行 Thread-7 正在运行 Thread-5 正在运行 Thread-3 正在运行 Thread-2 正在运行 Thread-4 正在运行 Thread-0 正在运行 Thread-5进入,并发数:4 Thread-9 正在运行 Thread-7进入,并发数:3 Thread-8 正在运行 Thread-6进入,并发数:2 Thread-1进入,并发数:1 Thread-7即将离开,并发数:4 Thread-5即将离开,并发数:4 Thread-1即将离开,并发数:4 Thread-2进入,并发数:4 Thread-6即将离开,并发数:4 Thread-4进入,并发数:4 Thread-0进入,并发数:4 Thread-3进入,并发数:3 Thread-3即将离开,并发数:4 Thread-4即将离开,并发数:4 Thread-0即将离开,并发数:4 Thread-2即将离开,并发数:4 Thread-8进入,并发数:4 Thread-9进入,并发数:4 Thread-8即将离开,并发数:2 Thread-9即将离开,并发数:2
当使用:公平锁时: private static Semaphore semaphore = new Semaphore(num,true);
仔细看结果,就会发现先运行的线程会优先处理
Thread-1 正在运行 Thread-5 正在运行 Thread-5进入,并发数:2 Thread-4 正在运行 Thread-4进入,并发数:3 Thread-2 正在运行 Thread-2进入,并发数:4 Thread-3 正在运行 Thread-0 正在运行 Thread-9 正在运行 Thread-8 正在运行 Thread-7 正在运行 Thread-6 正在运行 Thread-1进入,并发数:1 Thread-4即将离开,并发数:4 Thread-5即将离开,并发数:4 Thread-3进入,并发数:4 Thread-2即将离开,并发数:4 Thread-0进入,并发数:4 Thread-9进入,并发数:4 Thread-1即将离开,并发数:3 Thread-8进入,并发数:4 Thread-3即将离开,并发数:4 Thread-7进入,并发数:4 Thread-9即将离开,并发数:4 Thread-8即将离开,并发数:4 Thread-0即将离开,并发数:4 Thread-6进入,并发数:4 Thread-7即将离开,并发数:2 Thread-6即将离开,并发数:1