一、wait()、notify()、notifyAll()等方法基本概述
在Object.java中,定义了wait()、notify()和notifyAll()等接口。wait()的作用就是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的的锁;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
上述方法的详细信息如下:
notify() –唤醒在此对象监视器上等待的单个线程;
notifyAll() –唤醒在此对象监视器上等待的所有线程;
wait() —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,当前线程被唤醒(进入就绪状态);
wait(long timeout) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,当前线程被唤醒(进入就绪状态);
wait(long timeout,int nanos) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,或者其它某个线程中断当前线程,当前线程被唤醒(进入就绪状态)
二、wait()、notify()、notifyAll()代码实例
由于与wait配合起来使用时,notify()和notifyAll()并无太大区别。下面仅通过wait与notify()代码来进行演示
package Test;
/**
* Created by LKL on 2017/2/20.
*/
public class TestWaitAndNotify {
public static void main(String[] args) throws InterruptedException {
MyThread3 t1 = new MyThread3("t1");
// MyThread3 t2 = new MyThread3("t2");
synchronized(t1){
System.out.println(Thread.currentThread().getName()+" start t1");
// System.out.println(Thread.currentThread().getName()+" start t2");
t1.start();
// t2.start();
//主线程等待t1通过notify()唤醒
System.out.println(Thread.currentThread().getName()+" wait() ");
t1.wait();
//此时持有t1这个对象的锁的是object
System.out.println(Thread.currentThread().getName()+" continue ");
}
}
}
package Test;
/**
* Created by LKL on 2017/2/20.
*/
public class MyThread3 extends Thread{
public MyThread3(String name) {
super(name);
}
public void run(){
synchronized(this){
System.out.println(Thread.currentThread().getName()+" call notify()");
//唤醒当前线程
notify();
}
}
}
运行结果如下:
main start t1
main wait()
t1 call notify()
main continue
上述流程为:
(1)主线程main通过new MyThread3(“t1”)新建线程t1,接着通过synchronized(t1)获取”获取t1对象的同步锁”,然后调用t1.start()启动线程t1。
(2)主线程main执行t1.wait()释放”t1对象的锁”,并且进入了等待(阻塞)状态。等待t1对象上的线程通过notify()或notifyAll()将其唤醒。
(3)线程t1运行之后,通过synchronized(this)获取”当前对象的锁”;接着调用notify()唤醒”当前对象上的得带线程”,此时也就意味着唤醒主线程;
(4)线程t1运行完毕之后,会释放当前对象的锁,接着,主线程获取t1对象的锁,然后接着运行。
当把上述代码修改如下时:
package Test;
/**
* Created by LKL on 2017/2/20.
*/
public class TestWaitAndNotify {
public static void main(String[] args) throws InterruptedException {
MyThread3 t1 = new MyThread3("t1");
// MyThread3 t2 = new MyThread3("t2");
synchronized(t1){
System.out.println(Thread.currentThread().getName()+" start t1");
// System.out.println(Thread.currentThread().getName()+" start t2");
// t1.start();
// t2.start();
//主线程等待t1通过notify()唤醒
System.out.println(Thread.currentThread().getName()+" wait() ");
t1.wait();
//此时持有t1这个对象的锁的是object
System.out.println(Thread.currentThread().getName()+" continue ");
}
}
}
也就是不开启t1这个线程,此时主线程main运行了t1.wait()后,一直处于阻塞状态,因为并没有线程将它唤醒。
main start t1
main wait()
二、wait()、notify()总结
wait()会使当前线程等待,因为线程进入等待(阻塞)状态,所以线程应该释放它所持有的“同步锁”,否则其它线程获取不到这个“同步锁”而无法运行。
notify()和wait()直接就是依据“对象的同步锁”关联起来的。
假设我们把负责唤醒等待线程的那个线程称为唤醒线程,它只有在获取“该对象的同步锁”,此时的同步锁必须和等待线程的同步锁是同一个,并且调用notify()或调用notifyAll()方法之后,才能唤醒等待线程;但是它不能立刻执行,因为唤醒线程还持有该对象的同步锁,必须等到唤醒线程释放了对象的同步锁之后,等待线程才能获取到对象的同步锁,从而继续运行。
因此,notify()和wait()依赖于同步锁,而同步锁是对象所持有,并且每个对象只有一个。所以,wait()、notify()等方法定义在object类中,而不是Thread类中。
文章只是作为自己的学习笔记,借鉴了网上的许多案例,如果觉得阔以的话,希望多交流,在此谢过…