我正在使用Sockets进行Java项目。由于套接字方法是阻塞方法,我不得不制作一个多线程应用程序。
到目前为止,我能够读取来自其他应用程序的传入字节。我将它们写入StringBuilder。我的问题是如何将这个字符串返回到我的主线程。我在想一个类似事件的东西,只要套接字线程读完,我就可以调用它。
我很乐意有任何想法。
public class SocketRunnable implements Runnable {
private final Socket _socket;
public SocketRunnable(Socket socket){
this._socket = socket;
}
@Override
public void run() {
StringBuilder sb = new StringBuilder();
try {
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
this._socket.getInputStream()));
char[] buffer = new char[100];
int amountOfBytes = bufferedReader.read(buffer, 0, 100); // blocks until the message is received.
String message = new String(buffer, 0, amountOfBytes);
sb.append(message);
} catch (IOException ex) {
Logger.getLogger(SocketRunnable.class.getName()).log(Level.SEVERE, null, ex);
}
finally{
// Return (!)
}
}
我的问题是如何将这个字符串返回到我的主线程。
你不能;不是因为任何技术障碍,而是因为它在概念上没有意义。你的主线程已经开始了,你的返回值有意义的上下文已经丢失了。
所以,要么:
-
您的主线程必须阻塞才能接收结果(但是多线程有什么意义);
-
您的主线程已经以面向事件的方式从头开始设计,并且有一个外部事件循环,它将事件从队列中取出并处理它们(如果您正在构建GUI应用程序,这是真的)。
更有意义的是将结果提供给其他代码。这一切都可能发生在同一个线程中,即进行接收的线程。您可以通过简单地调用一个适当的方法来实现这一点。因此,在设计中要解决的问题是,如何使具有该方法的实例可用于在读取线程中执行的代码。
您可以将Callable
接口与Executors
结合使用。你可以在这里阅读:
可调用:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html
执行程序:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
只需使用SocketRunnable类实现可调用接口(有一个方法call()
,它将在完成后将值从一个线程返回到另一个线程)。
要将结果显示到Swing TextField中,您可以处理结果,一旦您有了字符串,只需执行:
final String msg=???; // Insert your string here
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textBox.setText(msg);
}
});
invokeLater调用将把您放到正确的线程上,以修改文本字段的内容。
在阻塞队列中写入结果String,并让该队列中的主线程poll
或take
。