调用wait()不会停止正确的线程

时间:2017-09-22 13:47:40

标签: java multithreading wait

我是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();
        }
    }
}

作家只是把东西写成输出(这里不重要)。 我已经添加了打印声明&#34; HERE 1&#34;和&#34; HERE 2&#34;显示程序失败的位置。基本上&#34; HERE 2&#34;永远不会到达。

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

实际输出是: 东西被写为输出3秒钟。 &#34; HERE 1&#34;打印。 东西继续显示为输出,没有暂停,没有&#34; HERE 2&#34;而程序永远不会停止。

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

2 个答案:

答案 0 :(得分:0)

wait()的文档说:

  

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

所以主要线程是在"HERE 2"之前等待的东西,因为它等待了,它永远不会到达notify

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

答案 1 :(得分:0)

  

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

没有

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

来实现

一个线程无法使 make 另一个线程调用一个函数。一个线程无法使另一个线程做任何事情。线程执行他们正在执行的代码告诉他们要做的事情,并且在一个设计良好的程序中,该代码告诉他们彼此合作。线程A可以通过询问线程B来执行某些操作,但是可以编写在线程A中运行的代码来执行查询,并且由你自己编写在线程B中运行的代码,该代码可以识别被问到什么时候,然后做任何事情。

*请参阅Oracle "guarded block" tutorial 注意!该教程没有使用&#34; monitor&#34;这个词,但它谈到了相同的模式。