java基础线程-wait+notify
2016-11-03 17:02
471 查看
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基础26 线程的通讯;wait()、notify()、notifyAll()等方法
- 重学JAVA基础(七):线程的wait、notify、notifyAll、sleep
- Java基础(高级)——多线程的理解和Synchronized实例,以及线程间通信,wait,notify等方法
- java线程同步原理及wait,notify的用法及与sleep的区别
- Java:使用wait()与notify()实现线程间协作
- java线程wait、notify、notifyAll
- 线程基础---wait(),notify的应用一例
- Java线程中sleep()、wait()和notify()和notifyAll()、suspend和resume()、yield()、join()、interrupt()的用法和区别
- java线程同步问题(一个理解wait()与notify()的例子)
- Java线程同步阻塞, sleep(), suspend(), resume(), yield(), wait(), notify()
- Java:使用wait()与notify()实现线程间协作
- Java【多线程知识总结(8)】线程通信,wait()与notify()的运用
- java线程的sleep(),wait(),notify(),yield()方法的区别要点
- 在Java线程中,wait、notify、notifyAll的用法
- Java 线程 Thread 对象锁的wait和notify解析
- Java【多线程知识总结(10)】线程通信之wait()与notify()的运用--模拟指挥官指挥2个连队交替轰炸战区<另外的写法>
- Java【多线程知识总结(10)】线程通信之wait()与notify()的运用--模拟指挥官指挥2个连队交替轰炸战区
- Java第七课 Java的多线程程序进程和线程的概念,实现多线程的两种方式,线程同步的原理,线程的死锁,运用wait和notify来实现producer - consumer关系,线程终止的两种情况。
- Java线程中sleep()、wait()和notify()和notifyAll()、yield()、join()等方法的用法和区别