java基础线程-wait+notify
来源:互联网 发布:2017年6月房地产数据 编辑:程序博客网 时间:2024/05/17 08:35
package common;/** * Created by shao on 2016/11/3. */public class ThreadTest implements Runnable{ int number=0; private Object lock; public ThreadTest(){ lock = new Object(); } public Object getLock() { return lock; } public void setLock(Object lock) { this.lock = lock; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " 我已开始运行了" ); synchronized(lock){ for (int i = 0; i < 5; i++) { try { number++; Thread.sleep(1000); if(i==3){ lock.wait(); } System.out.println(Thread.currentThread().getName() + " " +i); } catch (Throwable e) { System.out.println(e); } } } System.out.println(Thread.currentThread().getName() + " 我运行结束了" ); } public static void main(String args[]) { int number = 0; ThreadTest tt=new ThreadTest(); try { Thread th1 = new Thread(tt); th1.setName("邵飞飞是高手"); th1.start(); Thread th2 = new Thread(tt); th2.setName("高手"); th2.start(); Thread.sleep(10000); System.out.println("锁的时间达到10秒"); synchronized(tt.getLock()){ tt.getLock().notify(); } } catch (Throwable e) { System.out.println(e); } }}
对象的wait()是让当前线程释放该对象Monitor锁并且进入访问该对象的等待队列,当前线程会进入挂起状态,等待操作系统唤起(notify)
挂起的线程重新获取对该对象的访问锁才能进入运行状态。因为自身已经挂起,所以已经挂起的线程无法唤醒自己,必须通过别的线程
告诉操作系统,再由操作系统唤醒。Monitor是不能被并发访问的(否则Monitor状态会出错,操作系统根据错误的状态调度导致系统错乱),
而wait和nofity 正是改变Monitor的状态(请参考 PV操作) 所以使用wait、notify方法时,必须对对象使用synchronized加锁,只有线程获
取对象的Monitor锁之后才能进行wait、notify操作否则将抛出IllegalMonitorStateException异常
结果分析:
1. 两个线程无序都开始,结果第三行看出来,邵飞飞是高手 先运行,又因为run中的for循环有synchronized锁所以,高手 线程就等待中了。一直运行到结果的第5行
2. 因为在在i==3时我加了一个wait()锁,所以这时候 邵飞飞是高手 线程进行等待中,释放了for循环的synchronized,这时候 高手 线程开始运行。高手 线程运行到 i=3时又运行了lock.wait()函数,高手 线程也进入了等待中。这时候main函数中的sleep(10000)运行完了,lock.notify()运行了,lock对象释放了,这时候 邵飞飞是高手线程得到这个解锁的lock,因为在notify之前,两个线程都进入了wait set 队列(队列:先进先出;栈:先进后出),这时notify运行,lock对象解锁,邵飞飞是高手 线程在synchronized等待队列的最前面,所以,邵飞飞是高手比 高手 在次先运行一直运行结束
3. 等 邵飞飞是高手 线程运行结束之后,高手 线程开始运行for循环的部分,可是之前lock对象wait()了两次,现在只notify()一次,而且也被 邵飞飞是高手 线程抢走了,所以 高手 线程现在中的lock还是wait等待中,所以 高手 线程 永远也运行不到i=3及以后的代码,且这个线程永远是等待中,没有结束(除非被java当作垃圾回收)
4. 如果将notify()方法改为 notifyAll(),那么在notifyAll()执行之后,lock对象没有再wait()了,所以运行notifyAll()将 高手 邵飞飞是高手 两个线程中的wait()都解锁了,所以最后 高手 线程也会运行完的
声明:一个Object对象wait了几次就对应notify几次。
线程与线程之间是并行执行,单个线程内部的代码是串行执行的
synchronized(T){},T中不管为什么对象,{}中的代码都是被锁住的。但是如果本实验中的synchronized(lock){}改为synchronized(this),就会抛出IllegalMonitorStateException异常
Object.wait([time]);如果time为空的,即没有参数的,那要notify()才能打开锁。如果有参数的,即time!=null,那么不用notify()它也能在到达时间之后自己开锁,都都要在synchronized(Object){}的{}中
- java基础线程-wait+notify
- Java 线程 wait notify
- Java线程基础(三):线程调度以及wait/notify
- Java线程wait()与notify()
- java线程wait、notify、notifyAll
- java 线程同步 notify wait
- JAVA -- 线程wait()、notify()、notifyAll()
- JAVA线程 -- wait notify notifyAll
- java线程:wait,notify,notifyAll
- Java线程wait/notify讲解
- java 线程 wait() notify() 方法
- 【Java基础】wait(), notify(), notifyAll()
- Java线程同步 (synchronized wait notify)
- Java 线程的 wait()和notify()
- java线程中wait和notify 辨别
- Java线程同步(synchronized wait notify)
- Java线程同步 (synchronized wait notify)
- [Java] 线程之wait和notify
- 1.1 java 虚拟机如何启动的?启动之后都做了什么?
- MFC六大核心机制之二:运行时类型识别(RTTI)
- LeetCode 292. Nim Game
- javascript的计时器简单介绍
- 【BZOJ2959】【codevs2002】长跑,维护双联通分量
- java基础线程-wait+notify
- JS 取服务器时间
- Centos 7 docker 启动容器iptables报No chain/target/match by that name
- LeetCode 136. Single Number
- Java(Android)线程池
- 2016第二届中国网络营销行业大会通知
- Android 从源码的角度分析——为什么要用newInstance来实例化Fragment
- (十六)ArcGIS API For Javascript之调用地理编码服务
- CentOS中使用svn更换URL地址