Java多线程编程——wait()和notify()、notifyAll()
1、源码
wait() notify() notifyAll()都是Object类中方法。源码如下所示:
public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException; public final void wait() throws InterruptedException { wait(0); }
可以看到它们都是final native修饰的方法。
2、使用条件
首先我们需要明确的一点是wait() notify() notifyAll()都是需要在线程拥有对象锁的情况下使用。
在没有对象锁的情况下使用会抛出异常。执行下面代码,会抛出 java.lang.IllegalMonitorStateException 异常
package com.test; public class Test { public static void main(String[] args){ try { Object obj = new Object(); obj.wait(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
3、作用
3.1 wait()方法的作用
wait()方法能够使当前线程停止,进入阻塞序列,等待被唤醒。
wait()方法被调用后,当前线程会立即释放持有的对象锁。其他线程可以通过竞争的方式获取该对象锁。
唤醒处于阻塞状态的线程,需要其他线程使用notify()或者notifyAll()方法。
3.2 notify()方法的作用
notify()方法能够唤醒处于阻塞状态(处于阻塞队列中)的线程。
需要注意的是调用一次notify()方法只能唤醒一个处于阻塞状态的线程。
而且调用notify()方法后,当前线程不会马上释放锁,被notify 的线程也不会马上获取该对象锁,而是需要等待当前线程执行完同步代码块。
3.3 notifyAll()方法的作用
notifyAll()方法能够唤醒正在等待同意共享资源的所有线程。
4、实例
直接上代码咯。
package com.test; public class Test3 { class WaitThread implements Runnable{ private Object lock; public WaitThread(Object lock) { // TODO Auto-generated constructor stub super(); this.lock = lock; } @Override public void run() { // TODO Auto-generated method stub try { synchronized (lock) { System.out.println(Thread.currentThread().getName() + " 即将进入阻塞状态 wait time = " + System.currentTimeMillis()); lock.wait(); System.out.println(Thread.currentThread().getName() + " 结束阻塞状态 wait time = " + System.currentTimeMillis()); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } class NotifyThread implements Runnable{ private Object lock; public NotifyThread(Object lock) { // TODO Auto-generated constructor stub super(); this.lock = lock; } @Override public void run() { // TODO Auto-generated method stub try { synchronized (lock) { System.out.println(Thread.currentThread().getName() + " 即将唤醒 notify time = " + System.currentTimeMillis()); lock.notify(); System.out.println(Thread.currentThread().getName() + " 唤醒线程执行结束 notify time = " + System.currentTimeMillis()); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } public static void main(String[] args){ try { Object lock = new Object(); Test3 test3 = new Test3(); Thread waitThread = new Thread(test3.new WaitThread(lock)); waitThread.start(); Thread.sleep(3000); Thread notifyThread = new Thread(test3.new NotifyThread(lock)); notifyThread.start(); } catch (Exception e) { // TODO: handle exception } } }
5、总结
1 wait() notify() notifyAll() 方法只能在线程拥有对象锁的时候调用
2 wait()方法调用后 当前线程会立即释放锁
3 notify() notifyAll()方法执行后 当前对象并不会立即释放锁,而是要等同步代码块执行完成后才能释放锁
4 notify()方法每次调用后只能唤醒处于阻塞队列中的一个线程,如果需要唤醒等待当前资源的所有线程需要使用notifyAll()方法