【问题标题】:Calling wait() doesn't stop the correct thread调用 wait() 不会停止正确的线程
【发布时间】:2017-09-22 13:47:39
【问题描述】:

我是 java 多线程的新手。我正在尝试运行一个程序,该程序可以模拟多个将数据写入输出的“作家”。

我希望作者在某个时候都停下来,所以我对他们调用 wait(),但它不起作用。我知道问题出在哪里,但我不知道为什么会发生。

public void run() {
    ExecutorService executor = Executors.newFixedThreadPool(nbOfWriters);
    try {
        // Create a list with all the writers that should run at the same time
        Writer[] writers = new Writer[nbOfWriters];
        for (int i = 0; i < nbOfWriters; i++) {
            writers[i] = new Writer(i);
            executor.execute(writers[i]);
        }
        /*
        Expected outcome:
        start every writer -> wait 3 seconds
        pause every writer -> wait 3 seconds
        run every writer -> wait 3 seconds
        end
        */
        TimeUnit.SECONDS.sleep(3);
        for (Writer writer : writers) {
            synchronized (writer) {
                System.out.println("HERE 1");
                writer.wait();
                System.out.println("HERE 2");
            }
        }

        TimeUnit.SECONDS.sleep(3);
        for (Writer writer : writers) {
            synchronized (writer) {
                writer.notify();
            }
        }
        Thread.sleep(3);
        // End of the test
        for (Writer writer : writers) writer.end();
    } 
    catch (InterruptedException ex) {
        System.out.println(ex.getMessage());
    }
    finally {
        try {
            executor.shutdown();
            executor.awaitTermination(5, TimeUnit.SECONDS);
        } 
        catch (InterruptedException ex) {
            ex.getMessage();
        }
        finally {
            executor.shutdownNow();
        }
    }
}

作家只是把东西写成输出(这里不重要)。 我添加了打印语句“HERE 1”和“HERE 2”来显示程序失败的地方。基本上永远不会到达“HERE 2”。

理论上应该发生的情况是我将数据写入输出 3 秒,然后 3 秒没有任何内容,然后再次将数据写入输出。

实际输出为: 东西被写为输出 3 秒。 印有“这里 1”。 东西继续显示为输出,没有暂停,没有“HERE 2”,程序永远不会停止。

在我看来,wait() 正在停止错误的线程。

【问题讨论】:

    标签: java multithreading wait


    【解决方案1】:

    writer.wait() 不应该像其他方法一样在特定的编写器线程中调用 wait 吗?

    没有。

    语句writer.wait(); 使用writer 对象作为monitor。监视器旨在以非常特定的方式使用*。它允许一个线程等待某个(可能是未知的)其他线程完成任务。想要等待的线程调用o.wait();

    一个线程没有办法让make另一个线程调用一个函数。一个线程根本无法使另一个线程做任何事情。线程执行它们正在执行的代码告诉它们做的事情,并且在一个设计良好的程序中,该代码告诉它们彼此合作。线程 A 可以通过多种方式询问 线程 B 做某事,但由 编写在线程 A 中运行的代码来执行询问,然后就可以了让您编写在线程 B 中运行的代码,该代码可以识别何时被询问,然后执行任何操作。


    * 见Oracle "guarded block" tutorial
    笔记!本教程没有使用“监视器”这个词,但它谈论的是相同的模式。

    【讨论】:

      【解决方案2】:

      wait() 的文档说:

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

      所以主线程是在"HERE 2"之前等待的,由于它一直在等待,它永远无法到达notify

      我不确定是否有明确的方法来做你想做的事(告诉另一个线程等待)。有一些不推荐使用的 API 很好地解释了为什么你不应该使用它们:https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

      【讨论】:

      • 不应该像其他方法那样在特定的编写器线程中调用 writer.wait() 吗?
      • @Touniouk:哪些“其他方法”在与调用/当前线程不同的线程中执行?
      • @Touniouk 没有。 Java 并没有真正给你一种方法来强制另一个线程采取行动。您要做的是将您的请求传达给其他线程(并希望他们尊重它)。你可以通过一个信号或其他线程知道要检查的一些共享数据来做到这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 2015-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多