首页 > 解决方案 > 线程在java中的服务器客户端中存在多长时间?

问题描述

我有这个简单的服务器-客户端示例:

FooServer.java

public class FooServer {
    private Socket clientSocket;

    public class ClientHandler implements Runnable {
        private BufferedReader reader;
        private PrintWriter writer;

        public ClientHandler(Socket socket) {
            try {
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            String message;
            System.out.println("start of server run()");
            try {
                writer = new PrintWriter(clientSocket.getOutputStream());
                while ((message = reader.readLine()) != null) {
                    System.out.println("inside of server loop - get new message");
                    writer.println(message);
                    writer.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("end of server run()");
        }
    }

    public void go() {
        try {
            ServerSocket serverSocket = new ServerSocket(5000);
            while (true) {
                clientSocket = serverSocket.accept();
                Thread watchIncome = new Thread(new ClientHandler(clientSocket));
                watchIncome.start();
                System.out.println("got connection");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new FooServer().go();
    }
}

FooClient.java

public class FooClient {
    private BufferedReader reader;
    private PrintWriter writer;
    private Socket socket;

    public class ReadIncome implements Runnable {
        @Override
        public void run() {
            System.out.println("start of client run()");
            String mes;
            try {
                while ((mes = reader.readLine()) != null) {
                    System.out.println("inside of client loop");
                    System.out.println(mes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("end of client run()");
        }
    }

    public void go(String writeOut) {
        try {
            socket = new Socket("127.0.0.1", 5000);
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            writer = new PrintWriter(socket.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //--------HERE-----------
        //how long will this thread live?
        Thread readerThread = new Thread(new ReadIncome());
        readerThread.start();
        writer.println(writeOut);
        writer.flush();
    }

    public static void main(String[] args) {
        FooClient foo = new FooClient();
        foo.go("dummy text");
    }
}

我运行 FooServer.java,它又产生新的watchIncome(正在寻找来自客户端的消息的线程while ((message = reader.readLine()) != null))。但是在服务器中,它是while(true)无限循环的,所以它不断地产生新的线程来寻找传入的消息。

但是,在客户端,没有这样的无限循环。据我所知,Java 中的线程,一个线程运行该run()方法并且......它完成了。线程已死(即不能“重置”以再次运行)。而且由于客户端不会产生新线程(与服务器不同,没有无限循环),客户端不应该“等待”来自服务器的响应,因为线程应该已经死了(这就是我理解java中的线程的方式 -只需运行一次run()该方法)。

但是相反,客户端将挂在run()方法的中间 -> 它只会打印inside of client loop,并且永远不会完成。但这怎么可能,因为线程应该死了?一次readerThread.start();,在方法内部,该语句while ((mes = reader.readLine()) != null)将评估为 false(字符串没有任何内容,因此为空),并且方法完成,不应该等待服务器响应(因为我假设线程立即启动)。

而且 - 即使该语句确实评估为真(例如,服务器首先启动,所以客户端在它启动时就得到响应),客户端将 - 再次挂在客户端循环内部,在中间的run(),但它不应该,因为没有循环,所以它应该继续到方法的末尾(因此到线程的末尾)。最后,我必须终止服务器进程(这是有道理的,因为我从不关闭服务器套接字),但是这样,客户端进程也将结束。但它应该已经死了。有人可以解释一下,为什么客户“等待”,但不应该?

标签: javamultithreadingsocketsclient-server

解决方案


推荐阅读