RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1248590
Accepted
Николай Семенов
Николай Семенов
Asked:2022-02-25 22:23:25 +0000 UTC2022-02-25 22:23:25 +0000 UTC 2022-02-25 22:23:25 +0000 UTC

我不太明白 Object 类的等待和通知方法是如何工作的

  • 772

文章对此进行了如下说明: 不带参数的等待方法 导致当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll() 方法。换句话说,这个方法的行为就像它只是在做一个 wait(0) 调用一样。 https://java-en-blog.blogspot.com/2019/12/object-methods.html

有一个代码:

public class Main {
    public static void main(String[] args) {
        ThreadB threadB = new ThreadB();
        threadB.start();
        synchronized (threadB){
            try {
                threadB.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(threadB.total);
    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 5; i ++){
            total+=i;
            try {
                sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
/*        synchronized (this){
            notify();
        }*/
    }
}

一下子有两个问题:

  1. 即使 notify() 方法被注释掉,线程也会运行到最后,这与上面写的内容相矛盾。
  2. 如果取消注释notify(),就不是很清楚为什么调用这个方法是在线程内部(线程如何唤醒自己)
java
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Roman-Stop RU aggression in UA
    2022-02-25T23:02:19Z2022-02-25T23:02:19Z

    即使 notify() 方法被注释掉,线程也会运行到最后

    等待方法的文档说:

    中断和虚假唤醒是可能的,并且应该始终在循环中使用此方法:

    synchronized (obj) {
        while (<condition does not hold>)
            obj.wait();
        ... // Perform action appropriate to condition
    }
    

    这是惯用的使用方式wait- 始终在循环中,并在调用之前和之后检查条件wait。因为 你有一个综合的例子,很难说这里的条件是什么。对于订阅方的经典发布-订阅示例,等待条件为пока нет входящих сообщений.

    总而言之,问题在于虚假唤醒,即 在不合理的觉醒中。那些。wait即使没有 . 也可以返回控制权notify。

    目前还不是很清楚为什么对这个方法的调用在线程内部

    好吧,这就是你写它的方式:) 通常,对象不用于等待Thread,而是使用其他对象。通常这是线程之间共享的对象,它也用于发送通知。在与publish-相同的示例中,subscribe它可以是传输通知的队列。

    至少在这里看到一个适当的例子

    • 4
  2. tym32167
    2022-02-26T01:54:13Z2022-02-26T01:54:13Z

    我不是超级精通java,但我想当线程停止执行时调用Notify是Thread类的一个特性。也就是说,在您的代码中,主线程首先停止,然后子线程开始工作,当它完成时,它会在没有您参与的情况下自行调用通知,这将解锁主线程。要测试这个理论,请尝试注释掉 threadB.start(); 你的程序应该挂起,因为子线程永远不会完成它的工作(因为它甚至还没有启动它),这意味着它永远不会解除对主线程的阻塞。

    为了进行更干净的实验,我们不要锁定流对象,而只是锁定其他对象。例如

    class Solution {
    
        public static Object syncRoot = new Object();
    
        public static void main(String[] args) {
    
            ThreadB threadB = new ThreadB();
            threadB.start();
            synchronized (syncRoot) {
                try {
                    syncRoot.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(threadB.total);
    
    
        }
    }
    
    
    class ThreadB extends Thread {
        int total;
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                total += i;
                try {
                    sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (Solution.syncRoot) {
                Solution.syncRoot.notify();
            }
        }
    }
    

    我认为在这里,如果您注释掉该行,Solution.syncRoot.notify();程序将按预期挂起。

    • 1

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5