[Java] 线程之wait和notify

来源:互联网 发布:一分钟选股法公式源码 编辑:程序博客网 时间:2024/04/30 21:41

wait方法和notify方法来源于Object类,对wait方法的调用必须先获得监视器,然后在监视器上调用wait方法,意思是使当前线程在监视器上等待(即进入阻塞状态),直到被其它线程在同一个监视器上通知为止,然后解除阻塞状态,重新被安排调度执行,否则将一直阻塞。wait方法还有重载方法,即带有超时参数,表示该线程最大的等待时间,过了这个时间后,即便是没有其他线的通知,该线程也会自动解除阻塞状态,重新被安排调度执行。执行完wait后,监视器就会被释放掉,以供其它线程获得该监视器。

对notify方法的调用必须先获得监视器,然后在监视器上调用notify方法,意思是从之前在该监视器上等待的所有线程中解除一个线程,使它重新被安排调度执行,至于究竟解除的是等待线程中的哪一个,由系统决定,是随机的,并没有什么顺序。而且被解除的线程在重新被调度方面也不享有任何特权。还有一个相似的notifyAll方法,也必须先获得监视器,然后在监视器上调用notifyAll方法,意思是把之前在该监视器上等待的所有线程全部解除,使它们重新被安排调度执行,执行哪个被先调度执行,也是随机的,由系统决定。这些被解除的线程之间都是平等的,谁也没有任何特权。执行完notify或notifyAll后,监视器就会被释放掉,以供其它线程获得该监视器。

下面是简单的示例代码:

final Object monitor = new Object();final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Thread t1 = new Thread(new Runnable(){@Overridepublic void run() {System.out.println("线程1等待锁:" + sdf.format(new Date()));synchronized(monitor) {System.out.println("线程1获得锁:" + sdf.format(new Date()));try {System.out.println("线程1 wait:" + sdf.format(new Date()));monitor.wait();System.out.println("线程1获得锁:" + sdf.format(new Date()));System.out.println("线程1 wait over:" + sdf.format(new Date()));System.out.println("线程1 notify:" + sdf.format(new Date()));monitor.notify();} catch (InterruptedException e) {}}}});Thread t2 = new Thread(new Runnable(){@Overridepublic void run() {System.out.println("线程2等待锁:" + sdf.format(new Date()));synchronized(monitor) {System.out.println("线程2获得锁:" + sdf.format(new Date()));try {System.out.println("线程2 wait:" + sdf.format(new Date()));monitor.wait();System.out.println("线程2获得锁:" + sdf.format(new Date()));System.out.println("线程2 wait over:" + sdf.format(new Date()));System.out.println("线程2 notify:" + sdf.format(new Date()));monitor.notify();} catch (InterruptedException e) {}}}});Thread t3 = new Thread(new Runnable(){@Overridepublic void run() {System.out.println("线程3等待锁:" + sdf.format(new Date()));synchronized(monitor) {System.out.println("线程3获得锁:" + sdf.format(new Date()));try {System.out.println("线程3 wait:" + sdf.format(new Date()));monitor.wait();System.out.println("线程3获得锁:" + sdf.format(new Date()));System.out.println("线程3 wait over:" + sdf.format(new Date()));System.out.println("线程3 notify:" + sdf.format(new Date()));monitor.notify();} catch (InterruptedException e) {}}}});Thread t4 = new Thread(new Runnable(){@Overridepublic void run() {System.out.println("线程4等待锁:" + sdf.format(new Date()));synchronized(monitor) {System.out.println("线程4获得锁:" + sdf.format(new Date()));try {System.out.println("线程4 wait:" + sdf.format(new Date()));monitor.wait();System.out.println("线程4获得锁:" + sdf.format(new Date()));System.out.println("线程4 wait over:" + sdf.format(new Date()));System.out.println("线程4 notify:" + sdf.format(new Date()));monitor.notify();} catch (InterruptedException e) {}}}});t1.start();t2.start();t3.start();t4.start();Thread.sleep(2000);synchronized(monitor) {System.out.println("主线程 notify:" + sdf.format(new Date()));monitor.notify();}

下面是执行结果:

线程1等待锁:2012-11-04 15:05:32
线程1获得锁:2012-11-04 15:05:32
线程1 wait:2012-11-04 15:05:32
线程3等待锁:2012-11-04 15:05:32
线程3获得锁:2012-11-04 15:05:32
线程3 wait:2012-11-04 15:05:32
线程2等待锁:2012-11-04 15:05:32
线程2获得锁:2012-11-04 15:05:32
线程2 wait:2012-11-04 15:05:32
线程4等待锁:2012-11-04 15:05:32
线程4获得锁:2012-11-04 15:05:32
线程4 wait:2012-11-04 15:05:32
主线程 notify:2012-11-04 15:05:34
线程1获得锁:2012-11-04 15:05:34
线程1 wait over:2012-11-04 15:05:34
线程1 notify:2012-11-04 15:05:34
线程3获得锁:2012-11-04 15:05:34
线程3 wait over:2012-11-04 15:05:34
线程3 notify:2012-11-04 15:05:34
线程2获得锁:2012-11-04 15:05:34
线程2 wait over:2012-11-04 15:05:34
线程2 notify:2012-11-04 15:05:34
线程4获得锁:2012-11-04 15:05:34
线程4 wait over:2012-11-04 15:05:34
线程4 notify:2012-11-04 15:05:34

从执行结果可以看出每个线程执行完wait后就释放了锁,然后其它线程获得锁,执行wait,直到四个线程都执行了wait并进入了等待,主线程休眠了两秒后,获得了锁并执行了notify方法,通知一个线程解除,然后主线程释放了锁。线程1比较幸运,它被通知到了,然后重新获得了锁,阻塞被解除,它又执行了notify方法,然后释放了锁。剩余的三个线程将有一个被通知,这次是线程3,重复这样的过程,直到四个线程都被解除完。这就是线程的等待和通知机制。

如文章有错误之处,敬请之处,共同讨论!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 5岁宝宝咳嗽厉害怎么办 5岁宝宝咳嗽有痰怎么办 生川乌外贴中毒怎么办 7个月宝宝流鼻涕怎么办 脸上皮肤毛孔粗大有黑头怎么办 嗓子长了个囊肿怎么办 食管胃粘膜异位怎么办 狗狗肿瘤破了怎么办 婴儿胃食道反流怎么办 小儿胃食道反流怎么办 放疗后咳嗽痰多怎么办 胃息肉是恶性的怎么办 老是胃疼,胃胀怎么办 吃完饭之后胃胀怎么办 胃痛胃胀怎么办能缓解 胃胀不消化怎么办快速解决 便秘肛裂了好痛怎么办 胃消化慢还便秘怎么办 11个月婴儿便秘怎么办 80多岁老人便秘怎么办 狗狗便秘拉不出来怎么办 2个月幼犬便秘怎么办 狗狗便秘怎么办吃什么 痔疮又痛又痒怎么办 痔疮肉球特别痒怎么办 长了个小痔疮怎么办 产后4天没大便怎么办 7个月孕妇痔疮怎么办 运动完恶心想吐怎么办 跑步后恶心想吐怎么办 肠子不蠕动严重便秘怎么办 怀孕八个月严重便秘怎么办 怀孕七个月便秘严重怎么办 怀孕两个月便秘严重怎么办 3岁宝宝上火便秘怎么办 7个月的宝宝贫血怎么办 9个月婴儿贫血怎么办 肛裂大便有血怎么办 生完宝宝肛门痛怎么办 肛周脓肿出血了怎么办 胃胀怎么办简单的办法