Java 加入后线程卡住了
Java thread stuck after join
我有这个 Transmitter class,它包含一个 BufferedReader 和一个 PrintWriter。这个想法是,在主 class 上,对主套接字使用 Transmitter.receive() 和 Transmitter.transmit()。问题是:
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();
}
线程更改了 'outputMessage' 值,我可以使用辅助方法获取该值。问题是,如果没有加入,我的客户端会得到 outputMessage 但我想在我的主 class 上多次使用它,如下所示:
trans1.receive();
while(trans1.getOutput() == null);
System.out.println("message: " + trans1.getOutput());
但是加入这个 system.out 永远不会执行,因为 trans1.receive()
被卡住了...有什么想法吗?
编辑 1:这里是发射机 class https://titanpad.com/puYBvlVery
您可以发送\n
;这并不意味着您会在 Java 代码中看到它。
正如 Javadoc for BufferedReader.readLine()
中所说(强调我的):
(Returns) A String containing the contents of the line, not including any line-termination characters
所以 "\n"
将永远不会返回。
这样做:
{
Thread listener = new Thread(new Runnable() {
public void run() {
doSomeWork();
};
});
listener.start();
listener.join();
}
将创建一个新线程,然后等待它完成工作并完成。因此,它或多或少与直接执行相同:
doSomeWork();
新线程在这里没有任何实际用途。
此外,额外的线程会引入同步问题,因为在您的代码中您无法确保您的变量是同步的。
第三,您的线程一直在循环中从输入中读取行,直到没有更多内容可读为止,除非另一端关闭流,否则它将阻塞 readLine() 调用。您将在 getOutput() 中看到的是一条随机线,它恰好在您查看的那一刻就在那里,下次您查看时可能是同一行,也可能是一些完全不同的行;有些行会被立即阅读和遗忘,而你从主线程中没有注意到它。
当您确实需要从输入中获取换行消息时,您可以直接在主线程中调用 input.readLine(),不需要额外的 reader 线程。如果需要,您可以按照 yshavit 的建议将读取的消息存储到队列中,例如出于性能原因,最好在消息可用时立即读取消息并在内存中准备好它们。但是,如果您只需要一条一条地阅读消息,那么您只需在真正需要时调用 input.readLine() 即可。
我有这个 Transmitter class,它包含一个 BufferedReader 和一个 PrintWriter。这个想法是,在主 class 上,对主套接字使用 Transmitter.receive() 和 Transmitter.transmit()。问题是:
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();
}
线程更改了 'outputMessage' 值,我可以使用辅助方法获取该值。问题是,如果没有加入,我的客户端会得到 outputMessage 但我想在我的主 class 上多次使用它,如下所示:
trans1.receive();
while(trans1.getOutput() == null);
System.out.println("message: " + trans1.getOutput());
但是加入这个 system.out 永远不会执行,因为 trans1.receive()
被卡住了...有什么想法吗?
编辑 1:这里是发射机 class https://titanpad.com/puYBvlVery
您可以发送\n
;这并不意味着您会在 Java 代码中看到它。
正如 Javadoc for BufferedReader.readLine()
中所说(强调我的):
(Returns) A String containing the contents of the line, not including any line-termination characters
所以 "\n"
将永远不会返回。
这样做:
{
Thread listener = new Thread(new Runnable() {
public void run() {
doSomeWork();
};
});
listener.start();
listener.join();
}
将创建一个新线程,然后等待它完成工作并完成。因此,它或多或少与直接执行相同:
doSomeWork();
新线程在这里没有任何实际用途。
此外,额外的线程会引入同步问题,因为在您的代码中您无法确保您的变量是同步的。
第三,您的线程一直在循环中从输入中读取行,直到没有更多内容可读为止,除非另一端关闭流,否则它将阻塞 readLine() 调用。您将在 getOutput() 中看到的是一条随机线,它恰好在您查看的那一刻就在那里,下次您查看时可能是同一行,也可能是一些完全不同的行;有些行会被立即阅读和遗忘,而你从主线程中没有注意到它。
当您确实需要从输入中获取换行消息时,您可以直接在主线程中调用 input.readLine(),不需要额外的 reader 线程。如果需要,您可以按照 yshavit 的建议将读取的消息存储到队列中,例如出于性能原因,最好在消息可用时立即读取消息并在内存中准备好它们。但是,如果您只需要一条一条地阅读消息,那么您只需在真正需要时调用 input.readLine() 即可。