一、信号量
一个计数信号量。从概念上讲,信号量维护了一个许可集。Semaphore经常用于限制获取某种资源的线程数量。在java并发中,即Semaphore维护指定数量许可,当Semaphore中有额外(空闲)的许可时,线程获取到许可信号后(调用acquire()),线程才允许被执行,否则将被阻塞。当线程执行完毕,就会将占用的许可释放(调用release())。
此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证。当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。
二、用法
package com.dason.second;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* 信号量一般用于用于限制获取某种资源的线程数量
* @author Dason
*
*/
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
//创建一个管理 3 个许可的信号量
final Semaphore sp = new Semaphore(3);
for(int i=0;i<10;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
//获取一个许可,若没有则被阻塞
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
//availablePermits(): 返回此信号量中当前可用的许可数.
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*100));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
//释放一个许可.
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
}
}