您的位置:首页 > 编程语言 > Java开发

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){}的{}中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐