wait() notify() notifyAll()小结

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语句块中,因为无论哪个方法都要先获得同一个目标的监视器.

/**
 * 

wait()和notify()方法案例

*

* wait()和notify()方法必须包含在对应的synchronized语句块当中, * 无论是wait()还是notify都需要首先获得目标对象的一个监视器 *

*

* notify()和notifyAll()方法的区别在于: *

    *
  • notify():随机唤醒一个wait()的线程
  • *
  • notifyAll():唤醒全部wait()的线程
  • *
*

* *
 *     author      XueQi
 *     date        16/5/1
 * 
*/ 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的线程都被唤醒,而且是有顺序,不是同时被唤醒的.    



你可能感兴趣的:(Java)