java多线程wait为什么用while判断

在学习线程时遇到一个问题,为何wait操作通常与while循环结合使用而不是if。当容器满时,多个生产者会被wait。消费者取走数据后,若用notifyAll唤醒所有生产者,若wait在if中,生产者不会再次检查条件,可能导致错误。而while会在每次尝试前检查条件,避免了存储空间溢出的问题。总结:while用于循环判断,if仅做单次判断。
摘要由CSDN通过智能技术生成

最近在学习线程,发现一个有意思的面试题,wait为什么用while而不能用if?
这个是一个固定容量同步容器,拥有put和get方法

package yxxy.c_021;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class MyContainer1<T> {
	final private LinkedList<T> lists = new LinkedList<>();
	final private int MAX = 10; //最多10个元素
	private int count = 0;
	
	
	public synchronized void put(T t) {
		while(lists.size() == MAX) { //为什么用while而不是用if?
			try {
				this.wait(); //effective java
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		lists.add(t);
		++count;
		this.notifyAll(); 
	}
	
	public synchronized T get() {
		T t = null;
		while(lists.size() == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		t = lists.removeFirst();
		count --;
		this.notifyAll(); 
		return t;
	}
	
	public static void main(String[] args) {
		MyContainer1<String> c = new MyContainer1<>();
		//启动消费者线程
		for(int i=0; i<10; i++) {
			new Thread(()->{
				for(int j=0; j<5; j++) System.out.println(c.get());
			}, "c" + i).start();
		}
		
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		//启动生产者线程
		for(int i=0; i<2; i++) {
			new Thread(()->{
				for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
			}, "p" + i).start();
		}
	}
}

如果有n个生产者,n个消费者。当存储空间满了之后,假如n(大于1个)个生产者被wait,进入等待唤醒队列。当某个消费者取走了一个数据后,如果调用notifyAll(),则n个生产者线程都将被唤醒,如果此时生产者线程中的wait不在while循环中而是在if中,则这些生产者线程就不会再次判断是否符合执行条件,都将直接执行wait()之后的程序,那么如果其中一个生产者线程放入了一个数据至存储空间,则此时存储空间已经满了;但是其他生产者线程还是会继续往存储空间里放数据,错误便产生了。

最后我也总结了while和if的区别
while和if本身就用法不同,一个是循环语句,一个是判断语句。
if 只做判断,判断一次之后,便不会再回来了
while 的话,循环,直到结果为false,才跳出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值