有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程Javasocket异常:socket已关闭且值为空

我想创建一个能够连接多个客户端的服务器,但我总是得到“socketclosed”异常或从输入流中读取空值,以前我认为这是由于以错误的方式关闭Socket连接造成的,所以我发布了这个topic,但现在似乎不是问题所在

服务器方法

//here I use thread pool to solve concurrency issue
public static void main(String[] args) {

 try{
   ExecutorService service = Executors.newFixedThreadPool(4);
   ServerSocket serverSocket = new ServerSocket();

   while (true) {
      //keep listening
      Socket socket = serverSocket.accept();
      service.execute(new HandlerThread(socket));
   }
  }catch(Exception ex){
     ex.printStackTrace();
  }
}

手柄螺纹类

public class HandlerThread extends Thread{

    private Socket socket;
    private BufferedReader in;

    public HandlerThread(Socket socket) throws IOException {
        this.socket = socket;
        this.start();
    }

    public void run(){

        try {
            //Caches is a singleton class, which used to store the received data from client
            Caches caches = Caches.getInstance();

            //32 line
            in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            String line = in.readLine();

            //caches.list is an ArrayList
            synchronized (caches.globalCaches) {
                if (null != line) {
                    caches.globalCaches.add(line);
                }
            }

            System.out.println(line);

            in.close();
            socket.close();

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


}

客户端模拟器

public class Main {

    public static void main(String[] args) throws IOException, InterruptedException {

        for(int i = 0 ; i < 40; i++){
            Thread.sleep(2000);
            test test1 = new test();
            test1.start();
        }
    }

    public static class test extends Thread{

        public void run(){
            try {
                Socket socket = new Socket("localhost", 5050);

                PrintStream out = new PrintStream(socket.getOutputStream());
                out.println("Hello Server!");

                out.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

异常和问题

在客户端模拟器之前启动服务器,客户端模拟器没有任何异常,但是在服务器端,并没有收到所有数据,从控制台打印信息时,我看到“null”、“Hello server”、“java”。网SocketException:socket已关闭…',如下

Hello Server
null
null
Hello Server
java.net.SocketException: Socket is closed
Hello Server
    at java.net.Socket.getInputStream(Socket.java:876)
    at com.icubeidea.core.threads.HandlerThread.run(HandlerThread.java:32)
Hello Server

我研究了很长时间,仍然找不到到底是什么导致了这些异常和数据丢失的问题,还有服务器运行一段时间后是否存在可能导致内存泄漏问题的潜在风险


共 (1) 个答案

  1. # 1 楼答案

    问题似乎出在HandlerThread的构造函数中:

    您正在调用this.start();,这是您不应该调用的。尤其是在同时使用ExecutorService

    (在本例中,您正在创建一个新线程和start()同时告诉您的执行者运行相同的代码。最后,同一代码将在单个套接字上运行两次,这可能会导致各种问题,其中一个线程将关闭套接字,而另一个线程仍在尝试从中读取。这就是例外的真正来源。)

    解决方案:

    不要扩展线程,而是让HandlerThread只实现Runnable接口

    一旦您将该类的实例移交给执行器,它将负责运行run()方法;不需要自己开始任何线程