在Java

时间:2018-10-16 20:30:24

标签: java multithreading sockets

我正在读一本书“ 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;
            }
        }
    }
}

}

我真的不明白为什么会这样,为什么主线程想从另一个线程关闭套接字,是因为套接字对象是在主线程中创建的,而引用是在线程构造函数中提供的?

2 个答案:

答案 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。但是,此原理不能应用于此设计,因为在完成主线程后,线程可能需要资源。