wait()方法和notify()方法不是Thread类中的,而是属于Object类,这也意味着任何对象都可以调用这两个方法。Object.wait()方法和Object.notify()方法不是可以随便调用的,它们必须包含在对应的synchronized语句中,因为在调用它们之前首先要获得目标对象的一个监视器。
那wait()和notify()是如何工作的呢?
如果一个线程调用了object.wait()方法,那么它会进入Object对象的等待队列,并会立即释放synchronized(obj)中的obj的锁,这个等待队列中,可能会有多个线程。当object.notify()被调用时,它不会立即释放锁,必须要等notify()所在线程执行完synchronized(obj)块中的所有代码才会释放这把锁。而且它会从等待队列中随机选择一个线程将其唤醒,这种选择是不公平的,并不是先等待的线程会被优先选择。唤醒的线程的第一件事并不是执行后续的代码,而是先尝试获得object的监视器,只有获得监视器才能真正的执行后续的代码。
如下案例所示:
public class SimpleWN {
final static Object object = new Object();
public static class T1 extends Thread{
@Override
public void run() {
synchronized (object){
System.out.println(System.currentTimeMillis() + ":T1 start");
try {
System.out.println(System.currentTimeMillis() + ":T1 wait for object");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ":T1 end");
}
}
}
public static class T2 extends Thread{
@Override
public void run() {
synchronized (object){
System.out.println(System.currentTimeMillis() + ":T2 start! notify one thread");
object.notify();
System.out.println(System.currentTimeMillis() + ":T2 end!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
返回结果:
1577946765817:T1 start
1577946765818:T1 wait for object
1577946765818:T2 start! notify one thread
1577946765818:T2 end!
1577946767819:T1 end
注:Object.wait()和Thread.sleep()都可以让线程等待若干时间,除了wait()可以被唤醒外,它俩的主要区别是wait()方法会释放目标对象的锁,而Thread.sleep()不会释放任何资源