当前位置: 首页 > 面试题库 >

Java notify()在wait()之前运行?

籍辰沛
2023-03-14
问题内容
public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

如上面的示例,如果wait()先进入块,则notify()ThreadB中的后续块将告诉主线程继续。

但是我们不能保证wait()将在notify()之前执行,如果ThreadB首先进入该块怎么办?Notify()会在之前执行wait(),所以wait()会永远挂在那里(因为不再notify()告诉它继续执行)?通常有什么合适的方法来解决这个问题?


问题答案:

您几乎应该总是将谓词与等待/通知一起使用。也就是说,您需要可以检查的条件,例如变量变为true,队列变为空/满等。仅盲目地等待某人调用.notify()的用例很少。

因此,以下内容并不正确,由于您所说的原因,另一个线程可以在ThreadA调用.wait()之前调用.notify()。

public class ThreadA {
    public static Object latch = new Object();
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            latch.wait(); //wait for B to finish a calculation
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.latch.notify();
       }
    }
}

您需要执行以下操作:

 public class ThreadA {
    public static Object latch = new Object();
    public static boolean done = false;
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            while (!done) {   //wait for B to indicate it is finished.
                latch.wait(); 
            }
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.done = true;         
           ThreadA.latch.notify();
       }
    }
}

请注意,在上面,该done变量受同步块保护,.wait()将自动释放/重新获取该锁。因此,没有竞争条件,如果在进行调用之前.wait()调用了.notify(),则ThreadA会发现原因done是,因为将存在true且根本没有进入该.wait()调用。

对于这种代码这样的简单情况,您可以等待ThreadB结束,可以通过 b.join();



 类似资料:
  • 编写在非方法中,这段代码有什么不同吗... 也就是说,这两者的行为是相同的吗? 第二个代码片段没有阻塞正在执行的线程(非方法调用)而第一个代码片段阻塞了线程),这是否正确?

  • 如果你希望在每次运行 Puppet 之前执行命令,可以在配置文件中使用 prerun_command 配置。 类似地,你也可以使用 postrun_command 配置运行 Puppet 之后需要执行的命令。 这种机制为 Puppet 与其他软件的集成提供了强大的钩子,甚至可以触发其他机器上的事件。 prerun 和 postrun 命令必须能成功运行(即其返回的状态码为 0),否则 Puppet

  • 我想使用Mongock迁移工具来初始化存储在数据库中的应用程序配置。我遇到的问题是我的一个配置在使用@Configuration注释的类中使用。由于Mongock更改集在@Configuration之后执行,它无法从数据库中检索尚未存在的值,这会导致应用程序崩溃。有没有办法推迟创建@Configuration类?或者我应该在不使用mongock的情况下初始化这个配置?

  • 我最近发现了命令来自动碰撞包版本号并提交更改。这是一个神奇的小发现。 有没有可能在撞击前进行测试 我在google或堆栈搜索“npm version......”中找不到任何东西匹配了太多不相关的结果。并且没有关于文档npm-version中测试的信息 在这个发现之前,我一直在乞求编写一个脚本。为了测试,碰撞版本,然后git提交。 我用的是karma,package.json包含 在测试npm版本

  • 我想知道是否有办法调整TestNG,以便首先执行@AfterMethod注释的方法,然后运行测试监听器中的OnTestSuccess/OnTestFailure方法。 在我的项目中,由@AfterMethod注释的方法具有打印每个测试方法的响应体的逻辑。OnTestSuccess/OnTestFailure方法具有打印消息的逻辑(例如“测试完成”)。我不想把打印此消息的代码放在我项目中每个测试类的

  • 提前感谢! UPDATE:这是两个不同的查询,而不是delete查询中的语句。