双重校验锁模式【其他模式】

@Slf4j
public class DoubleCheckedLock {

	/**
	 * 双重校验锁模式可以避免多线程竞争时,无谓的资源消耗
	 */
	@Test
	public void all() throws InterruptedException {
		final LimitedList<String> list = new LimitedList<>(1);
		final CountDownLatch latch = new CountDownLatch(1);
		final ExecutorService threadPool = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 3; i++) {
			threadPool.submit(() -> {
				try {
					latch.await();
				} catch (final InterruptedException e) {
					log.error("failed", e);
				}
				list.add(Thread.currentThread().getName());
			});
		}
		latch.countDown();
		TimeUnit.SECONDS.sleep(3);
	}
}

@Data
@Slf4j
class LimitedList<E> {
	private final int maxSize;
	private final List<E> container;
	private final Lock lock;

	public LimitedList(int maxSize) {
		super();
		this.maxSize = maxSize;
		this.container = Lists.newArrayListWithCapacity(maxSize);
		this.lock = new ReentrantLock();
	}

	public boolean add(E e) {
		// 第一重校验
		if (container.size() < maxSize) {
			try {
				final String name = Thread.currentThread().getName();
				log.info("{} block1", name);
				lock.lock();
				log.info("{} block2", name);
				// 锁定后的第二重校验
				if (container.size() < maxSize) {
					log.info("{} block3", name);
					container.add(e);
					return true;
				}
			} finally {
				lock.unlock();
			}
		}
		return false;
	}
}

posted on 2018-12-24 21:15  竺旭东  阅读(98)  评论(0编辑  收藏  举报

导航