Java多线程之同步工具类(CountDownLatch、CyclicBarrier、Semaphore)

CountDownLatch

简介:CountDownLatch 可以使某一线程等待一组线程或者是任务等完成,否则await()会将其一直阻塞。
当然它也提供了等待超时的处理方法await(long timeout, TimeUnit unit),此类的使用效果和调用Thread的join()方法差不多:

public boolean await(long timeout, TimeUnit unit)
	throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

此类的使用场景,例如:当处理Excel的不同sheet数据处理的时候,多线程处理sheet之后,做个汇总结果之类的场景,或者是执行一些耗时的sql查询并最终汇总结果场景等。

示例代码:

/**
 * @author Kevin 2018-1-24
 * 
 * CountDownLatch : 等待一组线程或者一组任务、步骤完成。
 * CountDownLatch(num) 初始化会设置一个计数器,每调用一次countDown()就减一,直到为0为止结束。
 * 
 * CountDownLatch是使用实现AQS的内部类sync来完成的,AQS的操作是CAS机制的利用。
 */
public class CountDownLatchDemo {
	
	private static final CountDownLatch c = new CountDownLatch(2);
	
	public static void main(String[] args) {
		
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				c.countDown();
				System.out.println(Thread.currentThread().getName() + ": 执行完了。");
			}
		}).start();
		
		c.countDown();
		System.out.println(Thread.currentThread().getName() + ": 执行完了。");
		
		try {
			c.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}

CyclicBarrier

可以参考另一篇文章讲述的例子:
http://blog.csdn.net/kevin_king1992/article/details/73276318
简介:CyclicBarrier,同步屏障。允许一组线程互相等待到某个公共屏障点(CyclicBarrier.await()的地方就是屏障点),所有线程才会继续执行。

示例代码:

/**
 * @author Kevin 2018-1-24
 * 
 * CyclicBarrier:同步屏障。new CyclicBarrier(num);构造函数中设置的num int值,作为到达公共屏障点的数目,await()阻塞线程,直到num个线程到位,
 * 	否则一直阻塞下去。
 * 
 * 
 * CyclicBarrier提供了更为丰富的功能:
 * 
 * 1.reset() 方法:重置,让此操作重新再来一次。
 * 2.getNumberWaiting():获取等待的线程数量。‘
 * 3.isBroken():同步屏障是否损坏。
 * 4.await(long timeout, TimeUnit unit):同样提供了可供限时的阻塞等待操作。
 *
 */
public class CyclicBarrierDemo {

	private static final CyclicBarrier cb = new CyclicBarrier(2);
	
	public static void main(String[] args) {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					cb.await();
					System.out.println(Thread.currentThread().getName()+":start...");
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		try {
			cb.await();
			System.out.println(Thread.currentThread().getName()+":start...");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println("the current CyclicBarrier getNumberWaiting : " + cb.getNumberWaiting());
		System.out.println("the current CyclicBarrier getParties : " + cb.getParties());
		System.out.println("the current CyclicBarrier is Broken : " + cb.isBroken());
	}

}

有先决执行的构造函数:

/**
 * @author Kevin 2018-1-24
 * 
 * CyclicBarrier 构造函数中提供了new CyclicBarrier(2,new FirstRunnable()),
 * 它允许FirstRunnable当屏障门打开时先于其他任务执行。
 *
 */
public class CyclicBarrierDemo2 {

	private static final CyclicBarrier cb = new CyclicBarrier(2,new FirstRunnable());
	
	public static void main(String[] args) {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					cb.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":start...");
			}
		}).start();
		
		try {
			try {
				cb.await();
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+":start...");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	static class FirstRunnable implements Runnable {

		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName() + ": 优先执行完了。");
		}
		
	}
}

Semaphore

Semaphore:信号量

示例代码:

/**
 * @author Kevin 2018-1-24
 * 
 * Semaphore:信号量。
 * 
 * 在Semaphore的初始化方法中可以设置一个int类型的许可证数量,即为:允许同时执行的线程数量。就好比下面demo中的停车场车位,
 * 或者路口允许同时车辆通过的数量(并发编程的艺术一书中的举例)就容易理解的多。
 * 
 * 
 * 下面的例子就是车位10个,但是要停的车有50个,只有当有空闲车位(获取到信号量中的许可证)才可进去。
 * 
 * tryAcquire()此方法获取凭证,release()释放。从方法的名称就可以知道这是通过AQS(队列同步器)实现的,当然,提供的tryAcquire还远不止这个,
 * 还有等待超时等。
 * 
 *
 */
public class SemaphoreDemo {
	
	private static final Semaphore CARS = new Semaphore(10);
	public static void main(String[] args) {
		for(int i=0;i<50;i++) {
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + ":准备进入停车场");
					CARS.tryAcquire();
					System.out.println(Thread.currentThread().getName() + ":开始进入停车场");
					try {
						System.out.println(Thread.currentThread().getName() + ":停车中...");
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					CARS.release();
				}
			}).start();;
		}
	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值