首页 > 代码库 > JDK5新特性之线程同步工具类(三)

JDK5新特性之线程同步工具类(三)

一. Semaphore实现信号灯

Semaphore可以控制同时访问资源的线程个数, 例如: 实现一个文件允许的并发访问数.

Semaphore实现的功能就类似厕所有5个坑, 加入有十个人要上厕所, 那么同时只能有5个人能够占用, 当5个人中的任何一个人离开后, 其中在等待的另外5个人中就有一个可以占用了. 另外等待的5个人中可以是随机获得优先机会, 也可以使按照先来后到的顺序获得机会, 这取决于构造Semaphore对象时传入的参数选项.

/**
 * Semaphore:信号灯
 */
public class SemaphoreTest {

	public static void main(String[] args) {
		// 创建一个线程池
		ExecutorService es = Executors.newCachedThreadPool(); 
		
		// 允许并发访问的线程个数为3个
		final Semaphore sp = new Semaphore(3);
		
		// 开启10个线程
		for (int i = 0; i < 10; i++) {
			es.execute(new Runnable() {
				@Override
				public void run() {
					try {
						sp.acquire(); // 获取信号灯
						
						System.out.println("线程 " + Thread.currentThread().getName() 
								+ " 进入,当前有 " + (3 - sp.availablePermits()) + " 个并发!"); 
	
						Thread.sleep(2000);
						
						System.out.println("线程 " + Thread.currentThread().getName() + " 即将离开!");
						
						sp.release(); // 释放信号灯
						System.out.println("线程 " + Thread.currentThread().getName() 
								+ " 离开,当前有 " + (3 - sp.availablePermits()) + " 个并发!");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
		}
	}
}

单个Semaphore对象可以实现互斥锁的功能, 并且可以是由一个线程获得了"锁", 再由另一个线程释放"锁", 这可应用于死锁恢复的一些场合.


public class CyclicBarrierTest {

	public static void main(String[] args) {
	
		ExecutorService service = Executors.newCachedThreadPool();
	
		final CyclicBarrier cb = new CyclicBarrier(3);
		
		// 创建3个线程
		for(int i=0;i<3;i++){
			service.execute(new Runnable(){
				@Override
				public void run(){
					try {
						Thread.sleep((long)(Math.random() * 10000));//每个线程“休息的”时间不同   
						System.out.println("线程" + Thread.currentThread().getName()  
								+ "即将到达集合地点1,当前已有" + (cb.getNumberWaiting() + 1) 
								+ "个已经到达," + (cb.getNumberWaiting() == 2 ? "都到齐了,继续前进":"正在等候"));                       
						
						cb.await(); //先到的等待后到的,当3个都到达时才会继续向下执行
	
						Thread.sleep((long)(Math.random() * 10000));//每个线程“休息的”时间不同       
						System.out.println("线程" + Thread.currentThread().getName() 
								+ "即将到达集合地点2,当前已有" + (cb.getNumberWaiting() + 1) 
								+ "个已经到达," + (cb.getNumberWaiting() == 2 ? "都到齐了,继续前进":"正在等候"));
	
						cb.await(); 
	
						Thread.sleep((long)(Math.random()*10000));//每个线程“休息的”时间不同       
						System.out.println("线程" + Thread.currentThread().getName() 
								+ "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) 
								+ "个已经到达,"+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续前进":"正在等候"));                     
	
						cb.await();                     
					} catch (Exception e) {
						e.printStackTrace();
					}               
				}
			});
		}
		service.shutdown();
	}
}


JDK5新特性之线程同步工具类(三)