Java并发编程——条件队列

本文介绍了Java并发编程中的条件队列概念,它用于管理并发状态下对状态的依赖。条件队列通过wait(), notify(), notifyAll()方法实现线程的阻塞与唤醒,有效地减少了轮询的CPU开销。文章以有界缓存为例,展示了条件队列如何在不满足条件时挂起线程,并在条件满足时唤醒它们,同时讨论了notify方法的随机性和notifyAll方法的通知所有线程机制。" 112378356,10536940,微信小程序集成百度语音识别:STM32语音转文字实践,"['微信小程序开发', '语音转文字', '百度AI', 'STM32应用', '垃圾分类']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

状态依赖性:当进行下一步操作时必须先满足某个条件。例如,需要取出队列中的元素,必须依赖的状态是队列不为空;需要将元素放入缓冲区,依赖的状态是缓冲区还有空间。

在并发程序中,几条指令前队列可能还是为空,现在却为非空。在并发程序中对状态的管理我们先提供这两种办法:

  1. 轮询。不断询问是否满足条件。例如需要取出缓冲区的元素时不断询问缓冲区是否为空
    while (true){
        if (condition is satisfied){
            doSomething();
            break;
        }
    }
    while(true){
        if (condition is satisfied){
            doSomething();
            break;
        }
        Thread.sleep(); //进行休眠:在CPU响应速度和CPU使用率之间做出权衡
    }

     

  2. 阻塞。当发现条件不满足时阻塞,直到满足条件时才唤醒。
    while (condition is not satisfied){
        block();
    }
    doSomething();

     

轮询需要消耗额外的CPU时钟周期;而阻塞则需要有中断机制,否则可能无法跳出循环,也就无法正确结束程序,中断机制可以由调用者编写(throws Exception将异常抛给调用者),或者额外实现(try-catch捕捉异常,但需要由外界触发中断)

更好的办法是使用条件队列。条件队列实现的功能是:将不能满足的线程挂起,而当某个条件成真时将线程立刻唤醒。

条件队列就像厨房中烤面包机中的铃声。如果注意听铃声,当面包机烤好面包后可以立刻得到通知并取出面包。如果没有听到铃声(可能出去拿报纸),那么会错过通知信息,回来之后可以进行检查,如果烤好了再取出面包,如果没有,再次留意铃声。

正如每个Java对象都可以作为一个锁,每个对象同样可以作为一个条件队列。这个对象的wait,notify,notifyAll就构成了内部条件队列的API。对象的内置锁与条件队列是相互关联的。要调用对象X中条件队列的任何一个方法,必须先持有对象X上的锁。

可以把条件队列理解为面包机,排队等待使用面包机的人就是线程(条件队列的元素),面包机的铃声就是notify,notifyAll方法,当有人正在使用面包机时,等待使用面包机的人就会调用wait()方法将自己阻塞(可以去做别的事情),然后等待面包机的铃声。当使用notify方法时,会随机选中一个人使用面包机;当使用notifyAll方法时,所有人都会听到铃声,然后争夺使用面包机的权利(谁的拳头大谁先用,或者谁先把面包放进去谁先用,具体取决于操作系统的调度方式)

来看个例子

以下是有界缓存的基类

public class BaseBoundedBuffer<V>{
	private final V[] buf;
	private int tail;
	private int head;
	private int count;

	protected BaseBoundedBuffer(int capacity){
		this.buf = (V[])new Object[capacity];
	}

	protected synchronized final void doPut(V v){
		buf[tail] = v;
		if (++tail == buf.length){
			tail = 0;
		}
		count++;
	}

	protected synchronized final V doTake(){
		V v = buf[head];
		if (++head == buf.length){
			head = 0;
		}
		--count;
		return v;
	}

	public synchronized final boolean isFull(){
		return count == buf.length;
	}

	public synchronized final boolean isEmpty(){
		return count == 0;
	}
}
public class BoundedBuffer<V> extends BaseBoundedBuffer<V>{
	public BoundedBuffer(int size){
		super(size);
	}

	public synchronized void put(V v) throws InterruptedException{
		while (isFull()){
			wait();
		}
		doPut(v);
		notifyAll();
	}

	public synchronized V take()throws InterruptedException{
		while (isEmpty()){
			wait();
		}
		V v = doTake();
		notifyAll();
		return v;
	}
}

上面这个BoundedBuffer就是一个条件队列, 调用了put()和take()的线程就是队列的元素,当不满足条件时,调用队列的wait()方法阻塞,监测到铃声时,调用队列的notifyAll()通知队列元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值