示意图如下:



wait()和notify()一系列的方法,是属于对象的,不是属于线程的。它们用在线程同步时,synchronized语句块中。 我们都知道,在synchronized语句块中,同一个对象,一个线程在执行完这一块代码之前,另一个线程,如果传进来的是同一个object,是不能进入这个语句块的。也就是说,同一个对象是不能同时被两个线程用来进入synchronized中的。这就是线程同步。 wait()意思是说,我等会儿再用这把锁,CPU也让给你们,我先休息一会儿! notify()意思是说,我用完了,你们谁用? 也就是说,wait()会让出对象锁,同时,当前线程休眠,等待被唤醒,如果不被唤醒,就一直等在那儿。notify()并不会让当前线程休眠,但会唤醒休眠的线程。
先看第一个例子!
public class ThreadTest {
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T1 start!");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 end!");
}
}
};
Thread t2 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T2 start!");
object.notify();
System.out.println("T2 end!");
}
}
};
t1.start();
t2.start();
}
}
这第一个例子很简单,写了两个线程(分别是两个类,两个run方法)。两个run方法之间没有关系,但是,他们都用了同一个object!仔细看,T1里面主要写了个wait(),而T2里面主要写了个notify()。我们看到执行结果是:
流程可以这样解释:
值得一提的是,再强调一遍:
所以说,看上面的顺序,
是连续的,说明它并没有因调用了notify而暂停!
那么,如果两个线程都写wait没有线程写notify会有什么现象呢?试一下就知道了。
结果是,
道理很显然,T1先启动,然后wait了,T2获得了锁和CPU,在没有其它线程与它竞争的情况下,T2执行了,然后也wait了。 在这里,两个线程都在等待,没有其它线程将它们notify,所以结果就是无休止地等下去! 至少说明了一点,wait后如果没有其它线程将它notify,是绝不可能重新启动的。不可能因为目前没有线程占用CPU,某一个正在等待的线程就自动重启。
下面,我再把它改一下,写四个线程,分别是
public class ThreadF {
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T1 start!");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 end!");
}
}
};
Thread t2 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T2 start!");
object.notify();
System.out.println("T2 end!");
}
}
};
Thread t3 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T3 start!");
object.notify();
System.out.println("T3 end!");
}
}
};
Thread t4 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T4 start!");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T4 end!");
}
}
};
t1.start();
t2.start();
t3.start();
t4.start();
}
}
首先,大家知道,线程启动的顺序,和代码的先后顺序,理论上是没有关系的! 比如我这儿写的是按T1-T2-T3-T4的先后顺序先后start(),但实际上谁先启动,是有一定几率的。 执行上面代码,有两种结果:
我摘选了两种情况的输出结果,仅供参考:
1、可以执行结束的情况:
执行流程是:
2、不能执行结束,有线程由于没有其它线程唤醒,一直在等待中:
执行流程:
顺便说一下,如果没有线程在 wait,调用 notify 是不会有什么问题的,就像这样:
public class ThreadG {
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread() {
public void run()
{
synchronized (object) {
System.out.println("T1 start!");
object.notify();
System.out.println("T1 end!");
}
}
};
t1.start();
}
}

