JAVA-线程系列教程<4>-wait()\notify()和notifyAll()的区别和联系

若有雷同,请联系本人删除

wait();

notify();

notifyAll();

本文中的每句话都要好好理解,都有比较深刻的意义。

这三个方法都是Object的三个方法。


 只能在同步控制方法或同步控制块里调用wait(),notify()和notifyAll()。如果在非同步控制方法里调用这些方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常,并伴随着一些含糊的消息,比如"当前线程不是拥有者"。消息的意思是,调用wait(),notify()和notifyAll()的线程在调用这些方法前必须"拥有"对象的锁。

  可以让另一个对象执行某种操作以维护其自己的锁。要这么做的话,必须首先得到对象的锁。比如,如果要在对象x上调用notify(),那么就必须在能够取得x的锁的同步控制块中这么做:

synchronized(x){

  x.notify(); 

}

wait()方法,释放对象锁,让该线程等待。直到被notify或者被notifyAll

最后结论就是:被wait的线程,想要继续运行的话,它必须满足2个条件:

  1. 由其他线程notify或notifyAll了,并且当前线程被通知到了
  2. 经过和其他线程进行锁竞争,成功获取到锁了

Thread.sleep(long l);方法,不释放对象锁,让该线程睡眠l时间(单位是毫秒),过了睡眠时间,重新回到可执行状态


notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:

notifyAll使在该对象上所有wait状态的线程变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
notify则文明得多,他只是选择一个wait状态线程进行通知,并使它变成等待该对象上的锁,一旦该对象被解锁,它自己去执行。

即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象再次发出一个notify或notifyAll。


来来来,上例子:

package com.wyl.wait;

public class WaitTest1 implements Runnable{
    public int i5=0;
    public WaitTest1(int i5){
    	this.i5=i5;
    }
	@Override
	public synchronized void run() {
		i5=i5-1;
		if(i5>=2){
			System.out.println("wait方法研究2"+Thread.currentThread().getState());
			try {
				Thread.sleep(8000);
			    System.out.println("I'am over"+Thread.currentThread().getState());
				wait();
				System.out.println("我被解锁了"+Thread.currentThread().getState());
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			System.out.println("我来了兄弟们"+Thread.currentThread().getState());
			notifyAll();
		}
	}
	/**
	 * 运行流程如下:
	 * 1,新建线程tr,并start,打印  "刚创建1RUNNABLE"
	 * 2,tr新建完成后,发现run方法可用,cpu资源可用,那么马上进入。打印"wait方法研究2RUNNABLE",后来线程进入睡眠3s,这时候,主进程main方法要继续
	 * 3,新建线程tr2,并start
	 * 4,tr2打印"刚创建2RUNNABLE"
	 * 5,tr2调用start后,并不能立即执行,因为要等待tr的sleep()结束,因为此时方法被锁定,tr2并不能进入
	 * 6,过了8s,tr2进入了run方法,因为sleep()结束,目前tr在wait.直到他被notify或者notifyAll。此时tr释放了同步锁资源,允许tr2进来,
	 * 打印"我来了兄弟们RUNNABLE".唤醒了所有wait的线程
	 * 7,这时候tr从wait被唤醒了。所以继续执行,打印"我被解锁了RUNNABLE"
	 */
	public static void main(String[] args){
		WaitTest1 wt=new WaitTest1(3);
		Thread tr=new Thread(wt);
		tr.start();
		System.out.println("刚创建1"+Thread.currentThread().getState());
		Thread tr2=new Thread(wt);
		tr2.start();
		System.out.println("刚创建2"+Thread.currentThread().getState());
	}

}

好好理解吧,骚年们。

欢迎加我微信交流技术。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知乎关注八戒来了

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

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

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

打赏作者

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

抵扣说明:

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

余额充值