【问题标题】:Closing resources when thread is finished in Java在Java中线程完成时关闭资源
【发布时间】:2013-10-15 20:40:27
【问题描述】:

我有一个使用网络端口进行通信的线程。我添加了 cancel() 方法停止执行并关闭网络资源 (How to properly stop the Thread in Java?)

private class ServerThread extends Thread {
        int portNumber;
        String serverAddress = null;

        public ServerThread(String serverAddress, int portNumber) {
            super();
            this.serverAddress = "localhost";
            this.portNumber = portNumber;
        }

        @Override
        public void run() {
            ServerSocket listener;
            Socket socket;
            try {
                listener = new ServerSocket(this.portNumber);
                socket = listener.accept();
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));
                PrintWriter out = new PrintWriter(socket.getOutputStream(),
                        true);

                while (!isInterrupted()) {
                    String input = in.readLine();
                    if (input != null) {
                        out.println(input);
                        System.out.println("Hi:" + input);
                    }
                } // end of while loop
                System.out.println("OUT"); <-- ???
                socket.close(); <-- ???
                listener.close(); <-- ???
            } catch (IOException e) {
                e.printStackTrace();
            } 
        }

        public void cancel() {
            System.out.println("cancel called");
            interrupt();
        }
    }

问题是当我执行 ServerThread 并发送 cancel() 消息以完成执行时,这三行代码似乎从未执行过:System.out.println("OUT"); socket.close(); listener.close();

似乎我不需要发送 cancel() 消息来完成线程。

ServerThread s = new ServerThread(serverAddress, serverPortNumber);
s.start();
...
s.cancel(); // ???

关闭线程使用的资源的推荐方法是什么? 当不再使用线程时,我不必关闭资源吗?还是一切都只是自动处理?

添加

似乎线程被自动终止,因为这段代码正常工作。

            while(true) {
                String input = in.readLine();

                if (input != null) {
                    System.out.println("Received:" + input);
                    out.println(input);
                }
            } // end of while loop
            /* System.out.println("OUT");
            socket.close();
            listener.close(); */

【问题讨论】:

  • 不要interrupt()它。实施彻底停止。
  • 你在哪里打电话给cancel()?它会中断 当前 Thread。即Thread 调用cancel() 而不是你的ServerThread
  • @Sotirios Delimanolis - 我不确定 a clean stop 是什么意思,但我尝试 s.close() 警告它是一种已弃用的方法。
  • @Boris the Spider - 它是从其他线程调用的。顺便说一句,它应该是interrupt(),而不是Thread.currentThread().interrupt();。我更新了我的帖子。
  • 如果 readLine() 重新运行 null,您应该退出读取循环,并在此时关闭套接字。

标签: java multithreading sockets


【解决方案1】:

Thread#interrupt() 不会中断套接字上的阻塞 I/O 调用。尝试在 cancel() 方法中设置“停止”标志并关闭套接字,并在 while 循环中处理异常并检查标志。

InterruptibleChannels 对中断调用作出反应,但不是“老式”套接字流。

【讨论】:

    【解决方案2】:

    在 Java 7 中,您可以像这样使用 try (resource) {} catch 成语:

    try (final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
      while ((line = reader.readLine()) != null) {
        process(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    

    这将保证在离开 try 块后正确关闭流。无论内部发生什么或 try/catch 如何终止。

    【讨论】:

    • 我还要补充一点,代码应该使用十多年前引入的并发框架。无需扩展Thread 并处理线程生命周期管理。让Executor 为您做这件事。
    • 是的,当然。 executor可以做线程可以做的所有事情,只是更方便。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2022-01-25
    • 1970-01-01
    • 2010-10-12
    • 2018-04-12
    相关资源
    最近更新 更多