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()方法

原文地址:https://www.cnblogs.com/cuglkb/p/7275381.html