1.wait()和notify()是如何工作的?
这两个方法不并在Thread类中,而是在Object类中.这说明任何对象都可以调用这两个方法.这两个方法的方法签名如下:
public final void wait() throws InterruptedException;
public final native void notify();
当一个对象实例调用了wait()方法后,当前线程就会在这个对象上等待.比如,线程A中,调用了OBJECT.wait()方法,那么A线程就暂停了执行,转为等待状态,它会一直等待到其他线程调用了同一对象OBJECT.notify()方法为止.这时,这个OBJECT对象就成为两个线程之间有效的通信手段.
如果一个线程调用了OBJECT.wait(),那么它就会进入到一个线程等待的队列当中.这个等待队列当中,可能会有多个线程,因为系统多个线程都在同时等待某一个对象.当OBJECT.notify()被调用,JVM会从这个等待队列中,随机选择一个线程来唤醒.
要注意:上面的过程并不是公平的,不会因为你的线程优先级高,或者先进入等待队列而被优先选择,是完全随机的.
2.notify()和notifyAll()的区别
除了notify()方法外,Object类还有一个方法是:notifyAll()方法.它和notify()的用法基本一致,但不同的是,它会唤醒线程等待队列中所有等待的线程,而不是随机选择一个.
3.wait() notify() notifyAll()的使用方法
首先需要强调的是:这三个方法不是随便就可以调用的.它们必须包含在对应的synchronized语句块中,因为无论哪个方法都要先获得同一个目标的监视器.
/**
* <p>wait()和notify()方法案例</p>
* <p>
* wait()和notify()方法必须包含在对应的synchronized语句块当中,
* 无论是wait()还是notify都需要首先获得目标对象的一个监视器
* </p>
* <p>
* notify()和notifyAll()方法的区别在于:
* <ul>
* <li>notify():随机唤醒一个wait()的线程</li>
* <li>notifyAll():唤醒全部wait()的线程</li>
* </ul>
* </p>
*
* <pre>
* author XueQi
* date 16/5/1
* </pre>
*/
public class SimpleWaitNotify {
final static Object OBJECT = new Object();
public static class T1 implements Runnable {
@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 implements Runnable {
@Override
public void run() {
synchronized (OBJECT) {
System.out.println(System.currentTimeMillis() + ":T2 start!");
try {
System.out.println(System.currentTimeMillis() + ":T2 wait for object");
OBJECT.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ":T2 end!");
}
}
}
public static class T3 implements Runnable {
@Override
public void run() {
Thread.yield();
synchronized (OBJECT) {
System.out.println(System.currentTimeMillis() + ":T3 start! notify one thread");
OBJECT.notify();
System.out.println(System.currentTimeMillis() + ":T3 end!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class T4 implements Runnable {
@Override
public void run() {
Thread.yield();
synchronized (OBJECT) {
System.out.println(System.currentTimeMillis() + ":T4 start! notify all thread");
OBJECT.notifyAll();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ":T4 end!");
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
Thread t3 = new Thread(new T3());
Thread t4 = new Thread(new T4());
t1.start();
t2.start();
t3.start();
//t4.start();
}
}
当我们注释掉t4.start()时,执行main方法.我们可以看到控制台只有一个线程end,另外一个wait的线程由于监视器对象一直没有顺利获得.
当我们注释掉t3.start(),执行main方法,可以看到所有wait的线程都被唤醒,而且是有顺序,不是同时被唤醒的.
来源:oschina
链接:https://my.oschina.net/u/267473/blog/668584