我正在读一本书“ java网络第四版”,在第9章中有关服务器套接字的地方,同时解释了多线程服务器,其中每个客户端都是通过单线程处理的,它说:
示例9-3故意不对服务器接受的客户端套接字使用try-with-resources 插座。这是因为客户端套接字从try块转义到单独的线程中。 如果使用try-with-resources,则主线程将在获得套接字后立即关闭套接字 到while循环的结尾,很可能是在生成的线程使用完它之前。
这是例9-3
import java.net.*;
import java.io.*;
import java.util.Date;
public class MultithreadedDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeThread extends Thread {
private Socket connection;
DaytimeThread(Socket connection) {
this.connection = connection;
}
@Override
public void run() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
}
}
}
我真的不明白为什么会这样,为什么主线程想从另一个线程关闭套接字,是因为套接字对象是在主线程中创建的,而引用是在线程构造函数中提供的?
答案 0 :(得分:9)
这本书的意思是他们选择这样做
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
代替
try(Socket connection = server.accept()) {
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
因为使用try-with-resources块,它会在完成后立即关闭放在括号try(...)
中的内容。但是您不希望这种情况发生。 connection
套接字应保持打开状态,因为它将在启动的DaytimeThread
中使用。
答案 1 :(得分:4)
主线程不想关闭资源,因为生成的线程异步执行。
在try
中,task.start()
开始执行线程,但是它不等待线程完成。因此,main方法有可能(甚至有可能)在try
完成之前到达其DaytimeThread.run()
的结尾。
如果主方法的try
是try-with-resources,则此时连接将关闭。然后,随着DaytimeThread
在另一个线程中继续执行其工作,它将在关闭后尝试使用该连接。
但是要回答您的实际问题:
为什么主线程想从另一个线程关闭套接字
它不是另一个线程的套接字。实际上, main 方法是接受套接字连接,然后将其提供给DaytimeThread
。
通常,负责获取可关闭资源的实体也应负责将其关闭。实现此目的的简单方法是使用try-with-resources。但是,此原理不能应用于此设计,因为在完成主线程后,线程可能需要资源。