简体   繁体   English

加入后Java线程卡住了

[英]Java thread stuck after join

I have this Transmitter class, which contains one BufferedReader and one PrintWriter. 我有这个Transmitter类,其中包含一个BufferedReader和一个PrintWriter。 The idea is, on the main class, to use Transmitter.receive() and Transmitter.transmit() to the main socket. 在主类上,该想法是在主套接字上使用Transmitter.receive()和Transmitter.transmit()。 The problem is: 问题是:

 public void receive() throws Exception {
      // Reads from the socket
      Thread listener = new Thread(new Runnable() {
        public void run() {
          String res;

          try {
            while((res = input.readLine()) != null) {
              System.out.println("message received: " + res);

              outputMessage = (res);

            if (res.equals("\n")) {
              break;
            }
           }
        } catch (IOException e) {
          e.printStackTrace();
        }
      };
    });

    listener.start();
    listener.join();
  }

The thread changes the 'outputMessage' value, which I can get using an auxiliary method. 线程更改了“ outputMessage”值,我可以使用辅助方法来获取该值。 The problem is that, without join, my client gets the outputMessage but I want to use it several times on my main class, like this: 问题是,如果没有加入,我的客户会得到outputMessage,但是我想在主类上多次使用它,如下所示:

trans1.receive();
while(trans1.getOutput() == null);
System.out.println("message: " + trans1.getOutput());

But with join this system.out never executes because trans1.receive() is stuck... any thoughts? 但是加入这个trans1.receive()永远不会执行,因为trans1.receive()被卡住了...有什么想法吗?

Edit 1: here is the transmitter class https://titanpad.com/puYBvlVery 编辑1:这是发射器类https://titanpad.com/puYBvlVery

You might send \\n ; 您可以发送\\n ; that doesn't mean that you will see it in your Java code. 这并不意味着您会在Java代码中看到它。

As it says in the Javadoc for BufferedReader.readLine() (emphasis mine): 就像Javadoc中对BufferedReader.readLine()所说的(强调我的):

(Returns) A String containing the contents of the line, not including any line-termination characters (返回)一个包含行内容的字符串, 不包含任何行终止符

so "\\n" will never be returned. 因此"\\n"将永远不会返回。

Doing this: 这样做:

{
  Thread listener = new Thread(new Runnable() {
    public void run() {
      doSomeWork();
    };
  });

  listener.start();
  listener.join();
}

will create a new thread and then wait for it to do its work and finish. 将创建一个新线程,然后等待它完成工作。 Therefore it's more or less the same as just directly doing: 因此,它与直接进行的操作大致相同:

doSomeWork();

The new thread doesn't serve any real purpose here. 新线程在这里没有任何实际用途。

Also, the extra thread introduces synchronization problems because in your code you don't make sure your variables are synchronized. 另外,额外的线程会引入同步问题,因为在您的代码中您无法确保变量同步。

Thirdly, your thread keeps reading lines from the input in a loop until there's nothing more to read and unless the other side closes the stream, it will block on the readLine() call. 第三,您的线程将循环读取输入中的行,直到没有更多要读取的内容为止,除非另一端关闭流,否则它将阻塞readLine()调用。 What you will see in with getOutput() will be a random line that just happens to be there at the moment you look, the next time you look it might be the same line, or some completely different line; 您将在getOutput()中看到的是一条随机行,该行刚好在您看的那一刻出现,下一次您看它可能是同一行或完全不同的一行; some lines will be read and forgotten immediatelly without you ever noticing it from the main thread. 无需您从主线程注意到它,某些行将立即被读取和忘记。

You can just call input.readLine() directly in your main thread when you actually need to get a new line message from the input, you don't need an extra reader thread. 当您实际上需要从输入中获取换行消息时,只需在主线程中直接调用input.readLine()即可,而无需额外的阅读器线程。 You could store the read messages into a Queue as yshavit suggests, if that's desirable, eg for performance reasons it might be better to read the messages as soon as they are available and have them ready in memory. 您可以按照yshavit的建议将读取的消息存储到Queue中,如果需要的话(例如出于性能原因),最好在消息可用时立即读取它们并将它们准备好放在内存中。 But if you only need to read messages one by one then you can simply call input.readLine() only when you actually need it. 但是,如果您只需要一一阅读消息,那么仅在实际需要时才可以调用input.readLine()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM