【问题标题】:wait() does not force the thread to wait?wait() 不强制线程等待?
【发布时间】:2016-07-27 12:14:54
【问题描述】:

我有两个线程 t0 和 t1,它们分别在下面的代码部分 Run_0 和 Run1 中发布。我想要做的是,当 t0 正在写入或执行持续 7 秒的任务时,t1 应该等待。当 7 秒过去,应通知 t1 继续工作。我尝试使用 wait() 和 notify() 来做到这一点,但在运行时我希望 t0 启动但控制台只显示“T1 正在工作”并且 t0 没有打印任何内容,就好像它没有打印一样 开始

请告诉我为什么会发生这种行为。

代码

public static void main(String[] args) {

    t0 = new Thread(new Run_0());
    t1 = new Thread(new Run_1());

    t0.start();
    t1.start();
}

private static class Run_0 implements Runnable {

    public void run() {
        // TODO Auto-generated method stub

        while (true) {
            long startTime = TimeUtils.getTSSec();
            synchronized (t1) {
                try {
                    t1.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            System.out.println("T0 is writing");
            //simulate doing some work
            while( (TimeUtils.getTSSec()-startTime) <= 7) {

            }
            System.out.println("T0 finished writing");

            synchronized (t1) {
                t1.notify();
            }

            startTime = TimeUtils.getTSSec();

            while( (TimeUtils.getTSSec()-startTime) <= 7) {

            }
        }

    }

}

private static class Run_1 implements Runnable {

    public void run() {
        // TODO Auto-generated method stub

        while(true) {

            System.out.println("T1 is working");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

【问题讨论】:

标签: java android multithreading runnable


【解决方案1】:

来自javadocs(强调我的):

使当前线程等到另一个线程为此对象调用notify() 方法或notifyAll() 方法。

您的代码导致t0 等待,而不是t1

【讨论】:

    【解决方案2】:

    waitnotifynotifyAll 应该在 synchronized 块内。你有一个notify 在它外面:

            t1.notify(); // <-------
            startTime = TimeUtils.getTSSec();
    

    【讨论】:

    • 好的,我更正了代码,现在 t1.notify 在同步块内,但我仍然得到相同的结果
    • 虽然你的陈述是正确的,但它并不能解决问题。
    • @bradimus 编辑前的问题引用了正在发生的异常,现在它已被删除,不知道为什么(stackoverflow.com/posts/38612670/revisions)。
    【解决方案3】:

    控制台只显示“T1 正在工作”,而 t0 什么也不打印,就好像它没有启动一样

    是的,因为Run_0.run() 中的第一件事是t1.wait();。那是在等待有人打电话给t1.notify()t1.notifyAll()。我看没人这么叫。

    当线程在对象上调用wait() 时,它会导致线程等待对象上的监视器得到通知。一个线程不会导致另一个线程等待。它只能等待自己。

    重要的是要意识到您正在对恰好是一个线程的t1 对象进行同步、等待和通知。两个线程之间共享的任何对象都可以工作,由于我们对锁定 t0t1 线程对象感到困惑,因此您应该创建一个最终的锁定对象并锁定它:

    private final Object lock = new Object();
    

    t0 正在写入或执行其持续 7 秒的任务,t1 应该在等待。

    所以听起来你应该在Run_1 类中使用t1.wait() 而不是Run_0 类。也许Run_0 应该这样做:

    // much better way to simulate time passing instead of a spin loop
    Thread.sleep(7000);
    System.out.println("T0 finished writing");
    synchronized (lock) {
        lock.notify();
    }
    

    然后在Run_1 你会做类似的事情:

    synchronized (lock) {
        lock.wait();
    }
    System.out.println("T1 is working");
    

    请注意,我使用的是常见的 lock 对象。

    【讨论】:

    • 我认为 Run_1 应该包含: synchronized (t0) { try { t0.wait(); }
    • 无论您使用什么对象 @user2121。您只需要在两个线程中使用相同的对象。我会改变我的答案。
    • 我已经更新了我的答案@user2121,它试图解释使用线程对象会混淆你对object.wait()object.notify() 的理解。希望对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    相关资源
    最近更新 更多