java Semaphore-信号灯机制

当我们创建一个可扩展大小的线程池,并且需要在线程池内同时让有限数目的线程并发运行时,就需要用到Semaphore(信号灯机制),Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目,它是一个计数信号量,从概念上讲,信号量维护了一个许可集合,如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可,每个release() 添加一个许可,从而可能释放一个正在阻塞的获取者。        

 代码如下:

package com.qimh.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemahoreDemo {

	public static void main(String[] args) {  
        ExecutorService service = Executors.newCachedThreadPool();  
        final  Semaphore sp = new Semaphore(3);//定义有3个信号灯  
        for(int i=0;i<5;i++){  
            Runnable runnable = new Runnable(){  
                    public void run(){  
                    	 System.out.println("线程" + Thread.currentThread().getName() +"   " + System.currentTimeMillis());
                    try {  
                        sp.acquire();  
                    } catch (InterruptedException e1) {  
                        e1.printStackTrace();  
                    }  
                    //sp.availablePermits()指的是当前信号灯库中有多少个可以被使用
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "进入,当前已有" + (3-sp.availablePermits()) + "个并发" + "---"+sp.availablePermits() + "    " +System.currentTimeMillis()); //3-sp.availablePermits()就代表了当前有多少个线程在并发运行
                    try {  
                        Thread.sleep((long)(Math.random()*10000));  
                    } 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);            
        }  
        
        
        service.shutdown();
    }    

}

代码解析:

 该例子定义了一个newCachedThreadPool,在该Pool中利用for循环同时创建5个线程,现在通过Semaphore,创建一个只允许在线程池中有3个线程并发运行,sp.acquire()表示某个线程获得了一个信号灯,开始运行,在运行结束时,通过sp.release()还回这个信号灯,以便剩下的线程获得信号灯运行,sp.availablePermits()指的是当前信号灯库中有多少个可以被使用,由于例子中定义有3个信号灯,所以3-sp.availablePermits()就代表了当前有多少个线程在并发运行,上例运行结果如下:

线程pool-1-thread-1   1522397840180
线程pool-1-thread-1进入,当前已有1个并发---2    1522397840181
线程pool-1-thread-4   1522397840181
线程pool-1-thread-4进入,当前已有2个并发---1    1522397840181
线程pool-1-thread-3   1522397840181
线程pool-1-thread-3进入,当前已有3个并发---0    1522397840181
线程pool-1-thread-2   1522397840180
线程pool-1-thread-5   1522397840181
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-2进入,当前已有3个并发---0    1522397841645
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发---0    1522397845323
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-3已离开,当前已有1个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有0个并发

参考链接:https://blog.csdn.net/zzp_403184692/article/details/8017173

                 https://blog.csdn.net/u011613354/article/details/51150248

猜你喜欢

转载自my.oschina.net/qimhkaiyuan/blog/1787595