Java闭锁

介绍

一种常见的场景,当一个用户请求服务器,服务器为了响应,要进行一系列的操作,有可能需要去调用多个接口,等待各个接口返回结果,而各个接口之间相互独立,为了提高效率,一般会使用异步的方式。当所有异步线程都执行完毕后,通知主线程,主线程进一步执行下一步的逻辑,最终响应。那么主线程如何知道所有线程都完成了呢?本文介绍一种闭锁,让多个线程执行完后通知主线程,若未执行完,主线程阻塞,等待其执行完毕后再进行下一步操作。

原理

本文将例举一个常见的场景,来说明闭锁的原理。
例如:
BOSS下有Worker1,Worker2,Worker3,各个Worker都做着不同的事情,Boss准备当3个Worker都完成后才发工资。三个Worker同时开工。当一个Worker完成后,通知Boss,Boss知道后,就知道了还有2个Worker没有工作完,当再收到一个Worker的通知后,就知道还有1个Worker没工作,直到最后一个完成工作的Worker通知Boss,Boss才发工资。

代码实现

import java.util.concurrent.atomic.AtomicInteger;


public class Boss {
	public static void main(String[] args) {
		AtomicInteger latch = new AtomicInteger(3);
		new Thread(new Worker(latch, 1000)).start();
		new Thread(new Worker(latch, 2000)).start();
		new Thread(new Worker(latch, 3000)).start();
		
		while(latch.intValue() != 0){
			synchronized (latch) {
				try {
					latch.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}				
			}
		}
		System.out.println("发放工资");
	}
	
	private static class Worker implements Runnable{
		private AtomicInteger latch;
		private long sleepTime;
		public Worker(AtomicInteger latch,long sleepTime){
			this.latch = latch;
			this.sleepTime = sleepTime;
		}
		@Override
		public void run() {
			try {
				Thread.sleep(sleepTime);	//模拟Worker的工作花掉的时间
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally{
				latch.decrementAndGet();
				synchronized (latch) {
					latch.notifyAll();
				}
			}
		}
	}
}

输出结果:发放工资

以上为笔者自己模拟实现的闭锁,事实上,在JUC中,提供了CountDownLatch的一个类,用来简化闭锁的操作。

使用CountDownLatch实现闭锁如下:

import java.util.concurrent.CountDownLatch;

public class Boss {
	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(3);
		new Thread(new Worker(latch, 1000)).start();
		new Thread(new Worker(latch, 2000)).start();
		new Thread(new Worker(latch, 3000)).start();
		try {
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("发放工资");
	}
	
	private static class Worker implements Runnable{
		private CountDownLatch latch;
		private long sleepTime;
		public Worker(CountDownLatch latch,long sleepTime){
			this.latch = latch;
			this.sleepTime = sleepTime;
		}
		@Override
		public void run() {
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally{
				latch.countDown();
			}
		}
	}
}

输出结果:发放工资。

总结

本文简要介绍了闭锁的原理,并对其进行了代码实现。在介绍中,提出了接口的异步调用和闭锁的解决方法,但在实际场景中,往往需要判断其异步调用是否成功,此文中的两种方式都无法实现该需求,因此,接下来将提出另一种线程的构造方法,通过实现Callable接口构造线程,详情请参考笔者关于Callable的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值