wait() notify使用注意事项

1.wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题

2.不要使用if(队列size>最大个数) 否则真的会出现放入队列的size个数超过最大值的情况,推荐使用while

3.不要使用notify,推荐使用notifyall()

下面是生产者和消费者线程死锁方式和正确方式

package thred;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSONObject;


/**
 * 线程间通信
 * 执行结果
* @Description: TODO(用一句话描述该文件做什么) 
* @author min.zhang-2   
* @date 2017年12月19日 上午9:39:53 
* @version V1.0
 */
public class TestWaitNotify {

	public static void main(String[] args) {
		/*对应下面的注释1的类,如果生产者先过来,生产者想唤醒消费者,没有线程被阻塞唤醒结束
		消费者还没有被阻塞,这时候他请求过来,消费者线程被阻塞!!!!!
		执行结果:消费者等待吃苹果
		*/
		/*String nameString  = "test";
		Coustem Coustem =  new Coustem(nameString);
		Producer Producer = new Producer(nameString);
		
		Coustem.start();
		Producer.start();*/
		
		/***
		 * 实现了线程间通信的生产者和消费者,运行结果
		 * 
		 *  使用notifyall()的时候
		 *  生产者生产了2个2["3","3"]
			消费者消费掉了一个1["3"]
			消费者消费掉了一个0[]
			消费者开始等待
			生产者生产了2个2["3","3"]
			消费者消费掉了一个1["3"]
			消费者消费掉了一个0[]
			消费者开始等待
			
			使用notify的时候,总是等待生产者满了等待之后才唤醒消费者,为啥呢?,所以推荐使用notifyall()
			生产者生产了2个2["3","3"]
			生产者生产了2个4["3","3","3","3"]
			生产者生产了2个6["3","3","3","3","3","3"]
			生产者生产了2个8["3","3","3","3","3","3","3","3"]
			生产者生产了2个10["3","3","3","3","3","3","3","3","3","3"]
			生产仓库已经满了10开始等待
			消费者消费掉了一个9["3","3","3","3","3","3","3","3","3"]
		 */
		List<String> obList = new ArrayList<String>();
		Coustem Coustem =  new Coustem(obList);
		Producer Producer =  new Producer(obList);
		Producer.start();
		Coustem.start();
	}

}

/*****************这种方式就是死循环了*************/
/*class Coustem extends Thread{
	private Object lock;
	
	public Coustem(Object lock){
		this.lock=lock;
	}
	
	@Override
	public void run() {
		synchronized(lock) {
			try {
				System.out.println("消费者等待吃苹果");
				lock.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("消费者部分结束");
		}
	}
}

class Producer extends Thread{
	private Object lock;
	
	public Producer(Object lock){
		this.lock=lock;
	}
	
	@Override
	public void run() {
		
		synchronized(lock) {
			System.out.println("生产者生产了一个苹果");
			lock.notify();
			System.out.println("生产者部分结束");
		}
	}
}*/

/*********************************对应main的第二段 ,实现了生产者消费者**********/
class Producer extends Thread{
	private List<String> lock;
	
	public Producer(List<String> lock){
		this.lock=lock;
	}
	
	@Override
	public void run() {
		while(true){
			synchronized(lock){
				while(lock.size() >= 10) {
					System.out.println("生产仓库已经满了"+lock.size()+"开始等待");
					try {
						lock.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				lock.add("3");
				lock.add("3");
				System.out.println("生产者生产了2个"+lock.size()+JSONObject.toJSONString(lock));
				lock.notify();
			}
		}
	}
}

class Coustem extends Thread{
	private List<String> lock;
	
	public Coustem(List<String> lock){
		this.lock=lock;
	}
	
	@Override
	public void run() {
		while(true){
			synchronized (lock) {
				while(lock.size() == 0) {
					System.out.println("消费者开始等待");
					try {
						lock.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				lock.remove("3");
				System.out.println("消费者消费掉了一个"+lock.size()+JSONObject.toJSONString(lock));
				lock.notify();
			}
		}
	}
}



<think>好的,用户想了解Java中waitnotify的用法和区别。首先,我需要回忆这两个方法的基本概念,它们都属于Object类,用于线程间的协作。然后,考虑它们的用法,比如必须在同步块中使用,否则会抛出异常。需要解释wait会让线程释放锁,而notify会唤醒等待的线程。还要区分notifynotifyAll的不同。可能用户在使用多线程时遇到了协调问题,比如生产者-消费者模型。要结合实际例子说明,比如用synchronized块配合waitnotify实现线程等待和唤醒。同时,注意和sleep方法的区别,比如sleep不释放锁,而wait会释放。还要提到每个对象都有锁,所以waitnotify是针对对象监视器的。需要确保引用相关的参考资料,比如引用[4]中提到的sleep和wait的区别,这可能帮助用户更好地区分两者。最后,生成相关问题时要覆盖常见的使用场景、区别、常见错误以及替代方案等,帮助用户全面理解。记得检查是否符合格式要求,数学表达式用$...$,代码块正确,引用标识正确添加。</think>### Java中wait()notify()的用法与区别 #### 一、基本定义 1. **wait()** 是$Object$类的方法,调用后当前线程会释放对象锁并进入等待状态,直到其他线程调用该对象的$notify()$或$notifyAll()$方法[^4]。 ```java synchronized (obj) { obj.wait(); // 释放锁,线程进入等待队列 } ``` 2. **notify()** 同样是$Object$类的方法,唤醒在此对象监视器上等待的单个线程,具体唤醒哪个线程由线程调度器决定。 ```java synchronized (obj) { obj.notify(); // 唤醒一个等待线程 } ``` #### 二、核心区别 | 特性 | wait() | notify() | |---------------------|-----------------------------------------|------------------------------| | **锁释放** | 立即释放锁 | 不释放锁(需退出同步块才释放)| | **调用要求** | 必须在同步块内调用 | 同左 | | **线程状态** | 进入等待队列(WAITING) | 无状态变化 | | **作用目标** | 当前线程 | 其他等待线程 | #### 三、典型应用场景 **生产者-消费者模型** ```java // 共享资源 Queue<Integer> buffer = new LinkedList<>(); int MAX_SIZE = 5; // 生产者线程 synchronized (buffer) { while (buffer.size() == MAX_SIZE) { buffer.wait(); // 缓冲区满时等待 } buffer.add(data); buffer.notifyAll(); // 通知消费者 } // 消费者线程 synchronized (buffer) { while (buffer.isEmpty()) { buffer.wait(); // 缓冲区空时等待 } buffer.poll(); buffer.notifyAll(); // 通知生产者 } ``` #### 四、关键注意事项 1. **必须与synchronized配合使用** 直接调用$wait()/notify()$会抛出$IllegalMonitorStateException$异常。 2. **循环检查条件** 建议使用`while`而非`if`判断条件,避免虚假唤醒(spurious wakeup)。 3. **notifyAll()更安全** `notify()`可能因随机唤醒不匹配条件的线程导致死锁,`notifyAll()`会唤醒所有等待线程竞争锁。 #### 五、与sleep()的对比 | 对比维度 | wait() | sleep() | |----------------|-----------------------------------------|------------------------------| | **锁行为** | 释放锁 | 不释放锁 | | **所属类** | Object | Thread | | **唤醒条件** | 需其他线程调用notify()/notifyAll() | 时间到期后自动恢复 | | **用途** | 线程间协作 | 单纯的时间延迟 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值