Lock和Condition实现等待通知

Condition接口

目的:替代传统的Object的wait()、notify()。

相较于Object的wait()、notify(),使用Condition的await()、signal()来实现线程间的协作更加的安全,效率也更高。

使用wait、notify的前提是必须获取到监视器对象,否则会抛异常。因为wait会释放锁,释放锁的前提肯定是必须先拥有锁。

和wait、notify一样,使用await、signal的前提也是必须先获取到锁,否则也会抛异常。

如下:

public static void main(String[] args) throws InterruptedException {
	Lock lock = new ReentrantLock();
	Condition condition = lock.newCondition();
	condition.await();
}

Exception in thread "main" java.lang.IllegalMonitorStateException

Condition需要与Lock配合使用!

API

  • void await()
    线程进入等待状态。

  • void awaitUninterruptibly()
    线程进入等待状态,不理会中断。

  • long awaitNanos(long nanosTimeout)
    线程等待,支持纳秒级的超时,返回剩余时间。

  • boolean awaitUntil(Date deadline)
    线程等待,直到被通知,中断,或到达deadline时间。

  • void signal()
    唤醒一个等待在Condition上的线程。

  • void signalAll()
    唤醒所有等待在Condition上的线程。

使用示例

Condition内部维护了一个等待队列,当线程调用condition.await()时,会将当前线程封装成一个Node并添加到队列中,然后释放锁,供其他线程竞争。

调用condition.signal()时,会唤醒等待队列中等待时间最长的节点(头节点),并将该节点移出队列,该节点中的线程会继续竞争锁,执行逻辑代码。

经典的消费者生产者

public class ConditionDemo {
	//最大库存数
	private final int MAX_COUNT = 10;
	//库存数
	private volatile int goodsCount = 0;
	//随机决定线程休眠时间
	private Random random = new Random();
	//锁
	private Lock lock = new ReentrantLock();
	//生产者condition
	private Condition producerCondition = lock.newCondition();
	//消费者condition
	private Condition consumerCondition = lock.newCondition();

	public class Producer extends Thread {
		volatile boolean flag = true;
		@Override
		public void run() {
			while (flag) {
				lock.lock();
				try {
					if (goodsCount >= MAX_COUNT) {
						//System.err.println("库存满.");
						//库存满 停止生产 通知消费者消费
						consumerCondition.signalAll();
						producerCondition.await();
					}
					SleepUtil.sleep(random.nextInt(500));
					System.out.println("生产:"+(++goodsCount));
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
				}
			}
		}
	}

	private class Consumer extends Thread{
		@Override
		public void run() {
			while (true) {
				lock.lock();
				try {
					if (goodsCount <= 0) {
						//没有库存,停止消费 通知生产者生产
						//System.err.println("没有库存了..");
						producerCondition.signalAll();
						consumerCondition.await();
					}else {
						SleepUtil.sleep(random.nextInt(500));
						System.out.println("消费:" + (--goodsCount));
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
				}
			}
		}
	}

	public static void main(String[] args) {
		ConditionDemo demo = new ConditionDemo();
		//创建一个生产者
		demo.new Producer().start();

		//创建5个消费者
		for (int i = 0; i < 5; i++) {
			demo.new Consumer().start();
		}
	}
}
发布了100 篇原创文章 · 获赞 23 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_32099833/article/details/103217177