当前位置: 首页 > 工具软件 > Notify.js > 使用案例 >

Java Object 的 notify() 方法

湛安宁
2023-12-01

  我们都知道Java Object 中的 wait() 和 notify() 方法可以进行线程间的通信。

wait() 方法: 当前线程释放对象锁(监视器)的拥有权,在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,当前线程处于等待状态。

notify() 方法:唤醒在此对象锁(监视器)上等待的单个线程。如果有多个线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并且根据实现进行选择。

       这里说的一点就是,调用当前线程 noitfy() 后,等待的获取对象锁的其他线程(可能有多个)不会立即从 wait() 处返回,而是需要调用 notify() 的当前线程释放锁(退出同步块)之后,等待线程才有机会从 wait() 返回。这点自己之前理解得不清晰,举个例子加深一下:

等待线程

public class WaitThread implements Runnable{
    Object lock;

    public WaitThread(Object lock){
        this.lock = lock;
    }

    public void run() {
        String threadName = Thread.currentThread().getName();
        synchronized (lock){
            System.out.println(threadName + "开始进入同步代码块区域");
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + "准备离开同步代码块区域");
        }
    }
}

唤醒线程

public class NotifyThread implements Runnable{

    Object lock;

    public NotifyThread(Object lock){
        this.lock = lock;
    }

    public void run() {
        String threadName = Thread.currentThread().getName();
        synchronized (lock){
            System.out.println(threadName + "开始进入同步代码块区域");
            lock.notify();
            try {
                System.out.println(threadName + "业务处理开始");
                // 暂停 2s 表示业务处理
                Thread.sleep(2000);
                System.out.println(threadName + "业务处理结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + "准备离开同步代码块区域");
            //lock.notify();放在这一行唤醒,效果一样
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(threadName + "退出同步代码块后续操作");
    }
}

注意:lock.notify() 的位置和放在注释的位置,效果一样的,线程都会在执行完synchronized同步代码块之后才会释放锁,其他处于 wait() 线程才有可能被唤醒。

主程序

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread waitThread = new Thread(new WaitThread(lock), "waitThread");
        Thread notifyThread = new Thread(new NotifyThread(lock), "notifyThread");
        waitThread.start();
        Thread.sleep(1000);
        notifyThread.start();
    }
}

输出结果

waitThread开始进入同步代码块区域
notifyThread开始进入同步代码块区域
notifyThread业务处理开始
notifyThread业务处理结束
notifyThread准备离开同步代码块区域
waitThread准备离开同步代码块区域
notifyThread退出同步代码块后续操作

       可以看到waitThread线程必须等到notifyThread线程退出同步块释放锁之后,才会从 wait() 处返回。lock.notify() 放在注释掉的那一行,输出结果不变。不过在平常工作中,还是建议把 notify() 放在容易理解的位置。

 类似资料: