美文网首页
线程等待通知机制

线程等待通知机制

作者: 金馆长说 | 来源:发表于2017-04-17 16:41 被阅读14次

    机制的由来

    一 个 线 程 修 改 了 一 个 对 象 的 值, 而 另 一 个 线 程 感 知 到 了 变 化, 然 后 进 行 相 应 的 操 作, 整 个 过 程 开 始 于 一 个 线 程, 而 最 终 执 行 又 是 另 一 个 线 程。 前 者 是 生 产 者, 后 者 就 是 消 费 者, 这 种 模 式 隔 离 了“ 做 什 么”( what) 和“ 怎 么 做”( How), 在 功 能 层 面 上 实 现 了 解 耦, 体 系 结 构 上 具 备 了 良 好 的 伸 缩 性, 但 是 在 Java 语 言 中 如 何 实 现 类 似 的 功 能 呢?

    运行机制

    等 待/ 通 知 机 制, 是 指 一 个 线 程 A 调 用 了 对 象 O 的 wait() 方 法 进 入 等 待 状 态, 而 另 一 个 线 程 B 调 用 了 对 象 O 的 notify() 或 者 notifyAll() 方 法, 线 程 A 收 到 通 知 后 从 对 象 O 的 wait() 方 法 返 回, 进 而 执 行 后 续 操 作。 上 述 两 个 线 程 通 过 对 象 O 来 完 成 交 互, 而 对 象 上 的 wait() 和 notify/ notifyAll() 的 关 系 就 如 同 开 关 信 号 一 样, 用 来 完 成 等 待 方 和 通 知 方 之 间 的 交 互 工 作。

    主要方法

    image
    public synchronized void testRun() {
            System.out.println("执行 " + Thread.currentThread().getName());
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "执行结束");
        }
    
    
     public static void main(String[] args) throws InterruptedException {
    
            MainClass4 class4 = new MainClass4();
    
            //A线程中进入等待
            new Thread(new Runnable() {
                    @Override
                    public void run() {
                        class4.testRun();
                    }
             }).start();
           
            Thread.sleep(300);
    
            //B线程中唤醒
            synchronized (class4) {
                class4.notify();
            }
        }
    

    打印
    执行 Thread-0
    Thread-0执行结束

    唤醒全部
    notify只会唤醒待会此对象的线程,但是notifyAll会唤醒全部等待此对象的线程。

    public static void main(String[] args) throws InterruptedException {
    
            MainClass4 class4 = new MainClass4();
    
            for (int i = 0; i < 4; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        class4.testRun();
                    }
                }).start();
            }
            Thread.sleep(300);
            synchronized (class4) {
                class4.notify();
            }
    
            System.out.println("notifyAll");
            synchronized (class4){
                class4.notifyAll();
            }
        }
    

    输出
    执行 Thread-0
    执行 Thread-3
    执行 Thread-2
    执行 Thread-1
    notifyAll
    Thread-0执行结束
    Thread-1执行结束
    Thread-2执行结束
    Thread-3执行结束

    等待通知机制注意事项

    1. 调用必须在同步下进行
      可以看到代码中调用wait()和nofity、nofityAll的地方都加入了synchronized同步关键字,说明等待通知的调动必须在同步下进行。

    2. 等待和通知调用必须在不同线程
      代码中wait的地方是在一个子线程,notify的地方是在main线程,它们不是在一个线程的,这也满足之前说的作用于不同线程直接的通信

    3. 必须是同一把锁
      代码中的的synchronized用的都是class4对象的锁,等待通知机制如果不是同一把锁会报监视器错误

    Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notify(Native Method)
        at MainClass4.main(MainClass4.java:20)
    
    1. 必须是同一个对象
      等待的是那个对象,唤醒的就是那个对象

    相关文章

      网友评论

          本文标题:线程等待通知机制

          本文链接:https://www.haomeiwen.com/subject/whwtzttx.html