设计一个“重复使用”CountDownLatch进行线程阻塞的场景

模拟的场景是这样的:

在分布式环境中,使用redis分布式锁,当一个线程获取分布式锁后,其他线程不使用自旋,而是直接进入阻塞状态。已知的方式是可以使用redisson实现阻塞等待的情况。但是博主只是想模拟一下没用redisson的话是否可以通过单机的锁实现阻塞,减少线程对资源的消耗。

思路:

模拟获取锁失败,则获取map的锁,然后new一个CountDownLatch放入map中,然后开启一个线程传入CountDownLatch,查询是否释放了锁,如果完成更新则调用countdown()方法。主线程将CountDownLatch锁放入map中,调用await()方法进入等待。

其他线程获取锁失败,先查询map中是否已经存在CountDownLatch锁了,如果存在,则使用该锁,进入await();

上代码:

public class CountDownLatchTest {
	public HashMap lock = new HashMap();

	public void lock() {
		CountDownLatch countDownLatch = lock.get("lock");
		if (null == countDownLatch) {
			synchronized (lock) {
				countDownLatch = lock.get("lock");
				if (null == countDownLatch) {
					System.out.println("不存在锁!");
					countDownLatch = new CountDownLatch(1);
					lock.put("lock", countDownLatch);
					final CountDownLatch cd2 = countDownLatch;
					// 开启一个异步线程去查询
					new Thread() {
						public void run() {
							try {
								//模拟查询是否释放了锁
								Thread.sleep(5000);
								//解锁
								System.out.println("开始解锁!");
								cd2.countDown();
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							
						}
					}.start();
				} else {
					System.out.println("存在锁2!");
				}
				
			}
		} else {
			System.out.println("存在锁1!");
		}
		try {
			countDownLatch.await();
			System.out.println("开始执行业务!");
			//删除缓存
			lock.remove("lock");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		final CountDownLatchTest countDownLatchTest = new CountDownLatchTest();
		for(int i = 0; i < 5; i++) {
			new Thread() {
				public void run() {
					countDownLatchTest.lock();
				}
			}.start();
		}
		try {
			Thread.sleep(7000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for(int i = 0; i < 5; i++) {
			new Thread() {
				public void run() {
					countDownLatchTest.lock();
				}
			}.start();
		}
	}
}

结果:

设计一个“重复使用”CountDownLatch进行线程阻塞的场景_第1张图片

第一次写文章,请轻喷~

你可能感兴趣的:(java)