【问题标题】:Using try with resources in multithreaded server in java在java中的多线程服务器中使用资源尝试
【发布时间】:2019-03-21 11:14:20
【问题描述】:

我正在阅读《Java 网络第 4 版》和第 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;
            }
        }
    }
}

}

我真的不明白为什么会发生这种情况,为什么主线程要关闭另一个线程的套接字,是因为套接字对象是在主线程中创建的,并且引用是在线程构造函数中提供的?

【问题讨论】:

    标签: java multithreading sockets


    【解决方案1】:

    主线程不想关闭资源,因为生成的线程异步执行

    try 内,task.start() 开始执行线程,但不等待它完成。因此,main 方法有可能(甚至可能)在 DaytimeThread.run() 完成之前到达其 try 的末尾。

    如果 main 方法的 try 是 try-with-resources,则此时将关闭连接。然后,当DaytimeThread 继续在另一个线程中工作时,它会在关闭后尝试使用该连接。

    但要回答您的实际问题:

    为什么主线程要关闭另一个线程的套接字

    它不是来自另一个线程的套接字。实际上,ma​​in 方法是接受套接字连接,然后将其交给DaytimeThread

    通常,负责获取可关闭资源的实体也应负责关闭它。实现此目的的简单方法是使用资源尝试。但是,此原则不适用于此设计,因为在主线程完成资源后,线程可能需要资源。

    【讨论】:

      【解决方案2】:

      这本书的意思是他们选择这样做

      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 中使用。

      【讨论】:

      • 哦,我以为他们不想在线程的 run 方法中尝试资源。那么在run方法中对资源使用try就可以了吗?
      • 是的,在 writer 的 run 方法中使用它是完全可以的。
      猜你喜欢
      • 2018-04-20
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      • 1970-01-01
      • 2016-11-02
      相关资源
      最近更新 更多