【问题标题】:How to use wait() and notifyAll() to run thread one by one?如何使用 wait() 和 notifyAll() 来一一运行线程?
【发布时间】:2016-09-29 12:31:42
【问题描述】:

我写了一个House类,它有四个同步方法。 我写了四个线程,并希望它们一个接一个地运行。但是只有第一个和第二个运行了,另一个没有?

public class House {

    private boolean hasFoundation = false;
    private boolean hasFrame = false;
    private boolean hasWall = false;
    private boolean hasRoof = false;

    public synchronized void buildFoundation() {
        hasFoundation = true;
        System.out.println("foundation Ok");
        notifyAll();
    }

    public synchronized void buildFrame() throws InterruptedException {
        if (!hasFoundation) {
            wait();
        } else {
            hasFrame = true;
            System.out.println("frame ok");
            notifyAll();
        }
    }

    public synchronized void buildWall() throws InterruptedException {
        if (!hasFrame) {
            wait();
        } else {
            hasWall = true;
            System.out.println("wall ok");
            notifyAll();
        }
    }

    public synchronized void buildRoof() throws InterruptedException {
        if (!hasWall) {
            wait();
        } else {
            hasRoof = true;
            System.out.println("roof ok");
            notifyAll();
        }
    }
}

public class BuildAHouse {

    public static void main(String[] args) {
        House house = new House();

        ExecutorService exec = Executors.newCachedThreadPool();

        exec.execute(new FoundationTeam(house));
        exec.execute(new WallTeam(house));
        exec.execute(new RoofTeam(house));

        exec.execute(new FrameTeam(house));

        exec.shutdown();
    }
}

当运行 main() 时,结果只是: 基础还行 框架没问题

另外两个线程还没有运行!为什么?

...这样的团队类:

public class FoundationTeam implements Runnable {

    private House house;

    public FoundationTeam(House house) {
        this.house = house;
    }

    @Override
    public void run() {
        house.buildFoundation();
    }

}

这只是一个演示,我想知道如何使用wait()和notifyAll()。

请解决这个问题好吗?它只是我想做的所有事情的一部分。 请告诉我为什么它不起作用,以及如何解决?

当调用wait()时,这个对象不会被释放?而其他线程不能调用其他同步方法?

【问题讨论】:

  • 我不知道你在那些...Team 类中是什么,但你可能只执行了一次该方法。线程被暂停,当它们收到通知时,它们继续退出该方法,因为它们永远没有机会进入 else 子句,FrameTeam 除外
  • 我不认为你真的需要wait()notifyAll():你这里已经有ExecutorService,那是更高层次的同步抽象。见stackoverflow.com/q/2153663/5521491
  • 我认为这不是正确的用例。无论您试图实现这一目标,都可以轻松实现。等待通知的示例:1. 生产者消费者 2. 偶数打印机使用 2 个线程 3. 使用 3 个线程按顺序打印数字

标签: java multithreading java-threads


【解决方案1】:

如果你的方法确实 wait(),它不会在 else 块中运行任何东西

注意:wait() 可以虚假唤醒,建议使用 while 循环。

【讨论】:

  • 一个方法调用wait(),其他调用notifyAll()不能唤醒?
  • @Oolong 如果你 wait() 你没有做任何其他事情。
【解决方案2】:

另外两个线程还没有运行!为什么?

正如@Peter 提到的并且您已经发现,您需要在您的等待循环周围循环使用while(!boolean)。出于几个原因,这是必要的。

正如彼得所提到的,wait() 可能会因为虚假唤醒而不是正确的notify() 调用而返回。您需要确保您正在等待的条件已被实际设置,然后循环并再次调用wait()(如果尚未设置)。

但是,在您的情况下,它不是关于虚假唤醒,而是更多关于您的程序是如何编写的。因为您有一个synchronized 对象(House 对象),所以当您调用notifyAll() 时,所有团队线程都被唤醒。当调用buildFoundation() 方法时,它将hasFoundation 设置为true 并唤醒所有团队。但是只有框架团队才能真正开始工作——其他团队需要循环并等待一段时间,直到他们的布尔值设置为 true。

您可以更改您的代码以对每个步骤使用不同的锁,这将使代码更易于执行,尽管您仍然需要while 循环。

最后,正如您已经发现的那样,您的 if ... else ... 模式没有意义,因为当团队等待时,当他们收到通知时,他们的构建方法将返回,因为其他内容在 else 中。

【讨论】:

    【解决方案3】:

    成功了!

    public synchronized void buildWall() throws InterruptedException {
        while (!hasFrame) {
            wait();
        }
        hasWall = true;
        System.out.println("wall ok");
        notifyAll();
    }
    

    添加“while()”,但我已经不知道为什么了!

    【讨论】:

    • 因为你需要一直等到hasFrame 为真。 wait 函数不知道它在等待什么,也无法判断它等待的是否已经发生。所以这是你的责任。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2011-09-11
    • 2018-01-20
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多