Object类中提供了对象锁,其他的类都是继承自Object类,也都有对象锁,wait方法的作用是让持有对象锁的线程阻塞,直至被notify/notifyAll方法来唤醒,notify/notifyAll方法的作用是唤醒等待对象锁的线程。其中notify只随机唤醒一个当前等待对象锁的线程,而notifyAll则是唤醒当前所有等待对象锁的线程。
今天看到了一个现象,如果我们执行了notifyAll,而后面还有其他的语句块,那么会立刻唤醒其他的等待线程吗,答案是否。就像下面的示例
public class ProducerAndConsumer { public static void main(String[] args) { String str="aa"; new Thread(new MyRunnable(str)).start(); new Thread(new MyRunnable(str)).start(); } } class MyRunnable implements Runnable{ private String lock; public MyRunnable(String lock) { this.lock=lock; } @Override public void run() { synchronized (lock){ try{ System.out.println(Thread.currentThread().getName()+"开始执行"); lock.notifyAll(); Thread.sleep(5000); System.out.println(Thread.currentThread().getName()+"执行完毕"); }catch (Exception e){ } } } }
执行结果
Thread-0开始执行
Thread-0执行完毕
Thread-1开始执行
Thread-1执行完毕
我测试过多次;结果都是成对的出现,这也更加证明了调用notify/notifyAll方法时并没有立马唤醒其它等待的线程,而是等待同步块或者同步方法执行完毕之后才会去唤醒等待的线程。 如果说是执行完notify/notifyAll之后立马唤醒,那么总会有概率出现不是成对出现的。或许可以换一种方式来证明,更有说服力一些。
public class ProducerAndConsumer { public static void main(String[] args) { String str="aa"; new Thread(new MyRunnable(str)).start(); new Thread(new MyRunnable(str)).start(); } } class MyRunnable implements Runnable{ private String lock; public MyRunnable(String lock) { this.lock=lock; } @Override public void run() { synchronized (lock){ try{ System.out.println(Thread.currentThread().getName()+"开始执行"); lock.notifyAll(); Thread.sleep(5000); System.out.println(Thread.currentThread().getName()+"执行中"); Thread.sleep(5000); System.out.println(Thread.currentThread().getName()+"执行完毕"); }catch (Exception e){ } } } }
最后执行结果
Thread-0开始执行
Thread-0执行中
Thread-0执行完毕
Thread-1开始执行
Thread-1执行中
Thread-1执行完毕