欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java 信号灯 Semaphore

程序员文章站 2022-05-28 18:24:51
...
更多介绍http://blog.csdn.net/java2000_wl/article/details/23556859

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

/**
 * 信号灯  控制并发访问数量  
 * 只有 获取运行令牌(信号灯)后 ,才可以运行,当令牌(信号灯)使用完了,后面的访问 只能等着.直到有令牌被释放后,获取令牌才可以继续访问
 */
public class SemaphoreTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService service=Executors.newCachedThreadPool();
		final Semaphore sp=new Semaphore(3,true);  //先进来的先执行
		
		for (int i = 0; i < 10; i++) {
			
			Runnable runnable=new Runnable() {
				
				@Override
				public void run() {
					try {
						sp.acquire();//获取通行证
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} 
					System.out.println("线程"+Thread.currentThread().getName()+"进入,当前已有"+(3-sp.availablePermits())+"个并发");
					
					try {
						//System.out.println(new Random().nextLong());
						Thread.sleep(1000);
					} catch (Exception e) {
						// TODO: handle exception
					}
					System.out.println("线程"+Thread.currentThread().getName()+"即将离开");
					sp.release();
					System.out.println("线程"+Thread.currentThread().getName()+"已离开,当前已有"+(3-sp.availablePermits())+"个并发");
				}
			};
			service.execute(runnable);
		}
		
	}

}

实用场景:
Semaphore 分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。
     以一个停车场运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。


下面是模拟一个连接池,控制同一时间最多只能有50个线程访问。
import java.util.UUID;  
import java.util.concurrent.Semaphore;  
import java.util.concurrent.TimeUnit;  
  
public class TestSemaphore extends Thread {  
    public static void main(String[] args) {  
        int i = 0;  
        while (i < 500) {  
            i++;  
            new TestSemaphore().start();  
            try {  
                Thread.sleep(1);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 控制某资源同时被访问的个数的类 控制同一时间最后只能有50个访问 
     */  
    static Semaphore semaphore = new Semaphore(50);  
    static int timeout = 500;  
  
    public void run() {  
        try {  
            Object connec = getConnection();  
            System.out.println("获得一个连接" + connec);  
            Thread.sleep(300);  
            releaseConnection(connec);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public void releaseConnection(Object connec) {  
        /* 释放许可 */  
        semaphore.release();  
        System.out.println("释放一个连接" + connec);  
    }  
  
    public Object getConnection() {  
        try {/* 获取许可 */  
            boolean getAccquire = semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);  
            if (getAccquire) {  
                return UUID.randomUUID().toString();  
            }  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        throw new IllegalArgumentException("timeout");  
    }  
} 





相关标签: 线程信号灯