Java并发编程(十)Condition接口

一、Condition接口简介

java.util.concurrent.locks.Condition是java并发包中的一个接口,是为配合Lock提供的线程等待/通知功能。我们知道Object的监视器方法wait()和notify()配合sychronized关键字一样可以实现等待/通知机制,Condition的优势在于它可以为多个线程间建立不同的Condition,控制粒度更细。如阻塞队列同时有读写线程,该唤醒读线程还是写线程,notify方法无法直接指定,而Condition可以做到。

Conditon的所有方法:

public interface Condition {

	/**
	 * 线程进入等待状态,可被中断
	 * @throws InterruptedException
	 */
	void await() throws InterruptedException;

	/**
	 * 线程进入等待状态,不可被中断
	 */
	void awaitUninterruptibly();

	/**
	 * 线程进入等待状态,直到被中断、到达指定时间或唤醒
	 * @param nanosTimeout
	 * @return
	 * @throws InterruptedException
	 */
	long awaitNanos(long nanosTimeout) throws InterruptedException;

	/**
	 * 线程进入等待状态,直到被中断、到达指定时间或唤醒
	 * @param time
	 * @param unit
	 * @return
	 * @throws InterruptedException
	 */
	boolean await(long time, TimeUnit unit) throws InterruptedException;

	/**
	 * 线程进入等待状态,直到被中断、到达指定时间或唤醒
	 * @param deadline
	 * @return
	 * @throws InterruptedException
	 */
	boolean awaitUntil(Date deadline) throws InterruptedException;

	/**
	 * 唤醒一个等待线程
	 */
	void signal();

	/**
	 * 唤醒所有等待线程
	 */
	void signalAll();
}

二、Condition接口应用

典型应用就是LinkedBlockingQueue的实现,通过两个Condition分别控制读写线程的等待与通知,这里特别强调下,调用await方法和signal方法之前,该线程必须先获得锁,源代码如下:

public class LinkedBlockingQueue {

	private final ReentrantLock takeLock = new ReentrantLock();

	private final Condition notEmpty = takeLock.newCondition();

	private final ReentrantLock putLock = new ReentrantLock();

	private final Condition notFull = putLock.newCondition();

	public void put(E e) throws InterruptedException {

		// ...


		final AtomicInteger count = this.count;
		final ReentrantLock putLock = this.putLock;
        // 必须先获得锁才能调用condition方法
		putLock.lockInterruptibly();
		try {
            // 队列满时,通过notFull这个Conditon一直等待
			while (count.get() == capacity) {
				notFull.await();
			}

			// ...

		} finally {
			putLock.unlock();
		}

		// ...
	}

	public E take() throws InterruptedException {
		
		// ...
		
		final AtomicInteger count = this.count;
		final ReentrantLock takeLock = this.takeLock;
        // 必须先获得锁才能调用condition方法
		takeLock.lockInterruptibly();
		try {
            // 队列空时,通过notEmpty这个condition一直等待
			while (count.get() == 0) {
				notEmpty.await();
			}
			
			// ...
			
		} finally {
			takeLock.unlock();
		}
		
		// ...
	}
}

 

参考资料:

https://www.cnblogs.com/jalja/p/5895051.html

猜你喜欢

转载自blog.csdn.net/ss1300460973/article/details/84783784
今日推荐