概述
信号灯(Semaphore)是java5的新特性,仍然在java的并发库java.util.concurrent下。Java并发库的Semaphore 可以很轻松完成信号量控制,Semaphore分为单值和多值。单值只允许一个线程访问,多值允许多个线程同时访问。
举个例子,例如公司的打卡系统,如果有一个打卡机,那么一次就只能有一个人打卡,其余的人就被阻塞住,打卡完以后就可由下一个人打卡。如果有3个打卡机,那么一次就允许3个人或者少于三个人打卡,其余的人就得等待打卡机空闲下来才能继续打卡。
在信号量上我们定义两种操作: acquire(获取许可) 和 Release(释放)。信号量是一个非负整数,如上例中打卡机的数量。没当有人进行打卡,就会将该数量减一,当该数为0时。剩余的所有人(线程)都将处于等待。当有一个人打卡时,会调用acquire()方法,打卡机数量减一,打卡完成后,会调用Release()方法将打卡机空闲出来,排在后面的人就可以操作了。
当然了,信号量有公平和非公平模式。非公平模式允许后面的请求插队排在前面。
Semaphore(int permits, boolean fair)//permits为可通过的线程数,fair为是否为公平模式
其实要用信号灯来实现对线程的控制也非常简单,看个例子就会明白:
public class ThreadSemaphoreTest {
public static void main(String[] args) {
//启动线程池,有多少线程启动多少
ExecutorService pools = Executors.newCachedThreadPool();
//启动信号灯,设置一次可进入3个。是否公平默认的情况为true,所以直接new Semaphore(N)就行。
final Semaphore sem = new Semaphore(3,true);
//new10个线程
for(int i = 1 ; i < 10 ; i++){
//内部类使用外部类的变量必须是final型
final int index = i;
Thread thread = new Thread(new Runnable() {
public void run() {
try{
//获取许可
sem.acquire();
System.out.println("已进入"+index+"个线程,还可进入"+sem.availablePermits()+"个");
Thread.sleep(1000);
//释放资源
sem.release();
System.out.println("空余出"+sem.availablePermits()+"个");
}catch(Exception e){
e.printStackTrace();
}
}
});
pools.execute(thread);
}
pools.shutdown();
}
}
打印结果:
已进入1个线程,还可进入2个
已进入2个线程,还可进入1个
已进入3个线程,还可进入0个
空余出1个
已进入4个线程,还可进入0个
已进入6个线程,还可进入0个
空余出0个
空余出1个
已进入5个线程,还可进入0个
空余出0个
已进入8个线程,还可进入0个
空余出1个
已进入7个线程,还可进入0个
已进入9个线程,还可进入0个
空余出0个
空余出1个
空余出3个
空余出3个
从打印结果可以看出,虽然一次可进入三个线程,但并不是要等三个线程全部空出来才可以进入其他线程。而是只要有一个空闲,等待的线程立刻补上。这和现实生活中的情景式多么相似阿。由此可见,信号灯用来控制线程是很人性化的。
最后
以上就是欢喜小懒猪为你收集整理的09____java线程同步工具类之信号灯(Semaphore)的全部内容,希望文章能够帮你解决09____java线程同步工具类之信号灯(Semaphore)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复