java wait用法详解

本文详细介绍了Java中线程同步的重要方法,包括wait(), notify() 和 notifyAll() 的使用方式及注意事项。通过实例演示了如何利用这些方法实现线程间的等待与唤醒,以及如何设置超时唤醒。

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

一、wait(), notify(), notifyAll()等方法介绍

1.wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)

2.notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。

3.wait(long timeout)让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的notify()方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。

二、wait 的用法详解(这里的t1是一个线程(锁))

//     main(主线程)

synchronized(t1) {

       try {

              t1.start();

              t1.wait();

       } catch(InterruptedException e) {

              e.printStackTrace();

       }

}

//     在 t1 线程中唤醒主线程

       synchronized (this) {          //这里的 this 为 t1

              this.notify();

       }

注:

1、synchronized(t1)锁定t1(获得t1的监视器)

2、synchronized(t1)这里的锁定了t1,那么wait需用t1.wait()(释放掉t1)

3、因为wait需释放锁,所以必须在synchronized中使用(没有锁定则么可以释放?没有锁时使用会抛出IllegalMonitorStateException(正在等待的对象没有锁))

4. notify也要在synchronized使用,应该指定对象,t1. notify(),通知t1对象的等待池里的线程使一个线程进入锁定池,然后与锁定池中的线程争夺锁。那么为什么要在synchronized使用呢? t1. notify()需要通知一个等待池中的线程,那么这时我们必须得获得t1的监视器(需要使用synchronized),才能对其操作,t1. notify()程序只是知道要对t1操作,但是是否可以操作与是否可以获得t1锁关联的监视器有关。

5. synchronized(),wait,notify() 对象一致性

6. 在while循环里而不是if语句下使用wait(防止虚假唤醒spurious wakeup)

 三、证明wait使当前线程等待

class ThreadA extends Thread{
	public ThreadA(String name) {
		super(name);
	}
	public void run() {
		synchronized (this) {
			try {						
				Thread.sleep(1000);	//	使当前线阻塞 1 s,确保主程序的 t1.wait(); 执行之后再执行 notify()
			} catch (Exception e) {
				e.printStackTrace();
			}			
			System.out.println(Thread.currentThread().getName()+" call notify()");
			// 唤醒当前的wait线程
			this.notify();
		}
	}
}
public class WaitTest {
	public static void main(String[] args) {
		ThreadA t1 = new ThreadA("t1");
		synchronized(t1) {
			try {
				// 启动“线程t1”
				System.out.println(Thread.currentThread().getName()+" start t1");
				t1.start();
				// 主线程等待t1通过notify()唤醒。
				System.out.println(Thread.currentThread().getName()+" wait()");
				t1.wait();  //  不是使t1线程等待,而是当前执行wait的线程等待
				System.out.println(Thread.currentThread().getName()+" continue");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


四、wait(long timeout)超时被唤醒

class ThreadA extends Thread{
	public ThreadA(String name) {
		super(name);
	}
	public void run() {		
		System.out.println(Thread.currentThread().getName() + " run ");
		// 死循环,不断运行。
		while(true){;}	//	这个线程与主线程无关,无 synchronized 
	}
}
public class WaitTimeoutTest {
	public static void main(String[] args) {
		ThreadA t1 = new ThreadA("t1");
		synchronized(t1) {
			try {
				// 启动“线程t1”
				System.out.println(Thread.currentThread().getName() + " start t1");
				t1.start();
				// 主线程等待t1通过notify()唤醒 或 notifyAll()唤醒,或超过3000ms延时;然后才被唤醒。
				System.out.println(Thread.currentThread().getName() + " call wait ");
				t1.wait(3000);
				System.out.println(Thread.currentThread().getName() + " continue");
				t1.stop();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

参考:

http://www.jb51.net/article/40746.htm
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nachifur

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值