java - (Java, Socket) BufferedReader 阻塞线程,无法 .close()

标签 java multithreading sockets server client

因此,我为我的树莓派编写了一个客户端-服务器应用程序 - 为了处理服务器上的多个客户端,我总是为每个客户端套接字打开一个新的“ClientMessageListener”线程。

我尝试创建一个销毁链,当我想要关闭 ServerSocket 时会调用该销毁链。它遍历每个线程并调用 ClientMessageListener 的 destroy 方法,该方法应该关闭连接资源,然后关闭套接字本身。

我的客户端处理程序如下所示:

package com.imnos.piserver.server.serversocket.client;

import com.imnos.piserver.server.serversocket.ServerRequestController;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
* @author simon
*/
public class ClientMessageListener implements Runnable {

    private static final ServerRequestController SRC
            = ServerRequestController.getInstance();

    private Socket clientSocket = null;

    private PrintWriter out = null;
    private InputStreamReader inputStream = null;
    private BufferedReader in = null;

    ClientMessageListener(final Socket clientSocket) {
        this.clientSocket = clientSocket;
        this.initDataStream();
    }

    /**
     * @return
     */
    synchronized boolean destroyClientMessageListener() {

        if (this.clientSocket == null) {
            return false;
        }

        if (this.in != null) {

            try {

                this.in.close(); // Method stucks here

            } catch (IOException ignore) {
                ignore.printStackTrace();
            } finally {
                this.in = null;
            }

        }

        if (this.inputStream != null) {

            try {

                this.inputStream.close();

            } catch (IOException ignore) {
                ignore.printStackTrace();
            } finally {
                this.inputStream = null;
            }

        }

        if (this.out != null) {

            this.out.close();
            this.out = null;

        }

        return true;
    }

    /**
     * @return
     */
    private synchronized boolean initDataStream() {

        if (this.clientSocket == null) {
            return false;
        }

        if (this.clientSocket.isClosed()) {
            return false;
        }

        try {

            this.out = new PrintWriter(
                    this.clientSocket.getOutputStream(), true);

            this.inputStream = new InputStreamReader(
                    this.clientSocket.getInputStream());

            this.in = new BufferedReader(this.inputStream);

            return true;

        } catch (IOException ex) {

            this.destroyClientMessageListener();
            ex.printStackTrace();

        }

        return false;
    }

    /**
     *
     */
    @Override
    public void run() {

        if (in != null) {

            String strInput;

            try {

                while ((strInput = this.in.readLine()) != null) {

                    final boolean success
                        = SRC.handleIncoming(
                            this.clientSocket, strInput);

                }

            } catch (IOException ignore) {
                ignore.printStackTrace();
            }

        }

    }

}

一切正常,当我在 destroy() 方法中关闭资源时,我希望 this.in.readLine() 调用抛出 IOException,以便线程结束。但是,当调用 this.in.close() 时, destroy 方法会阻塞,并且绝对不会抛出异常。

即使 Thread.getCurrentThread.interrupt() 也不起作用,我不知道为什么。是否有一个干净的解决方案来关闭资源并结束 run() 方法?

最佳答案

关闭输入套接字。这将导致 readLine() 返回 null,从而导致正在读取套接字的线程将其关闭并退出。

关于java - (Java, Socket) BufferedReader 阻塞线程,无法 .close(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46237542/

相关文章:

c# - 使用 TcpClient/Socket 安全传输/发送大数据包

c# - 如何检测到我尝试通过 TLS 安全套接字发送数据失败?

Java 多线程与 Shell 脚本

java - 读取数组中文件数据的最快方法(Java)

java - 在 Java 中执行 ActionPerformed 期间更新 JTextFields

c - 套接字编程问题

java - Java HashSet.isEmpty() 中的 NPE

java - Gradle:如何从 JScience jar 依赖项中排除 javax.realtime 包(多个 dex 定义)

java - 线程正在执行,给出 "interrupt()"后

JavaFX:用线程移动一个圆圈