【问题标题】:How to resume/Restart a thread in Java after an exception is caught?捕获异常后如何在Java中恢复/重新启动线程?
【发布时间】:2018-10-10 00:11:07
【问题描述】:

最近,我一直在玩 Java 的网络和线程功能,作为背景,我正在尝试开发一个多线程聊天应用程序。

问题在于,当客户端发送使用错误格式的消息时,例如: “UserID#Message”而不是“UserID*Message”抛出异常,线程完全停止,客户端需要关闭他的会话并重新打开它以重新建立与服务器的连接,而不是在错误后恢复,我无法恢复它。

这是服务器代码:

package AdvanceThreading.Server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {

    private ServerSocket serverSocket;
    private Socket socket;

    private DataInputStream messageFromClientToHandler;
    private DataOutputStream messageFromHandlerToRecipient;

    private int port;
    private static int userID;
    private ArrayList<ClientHandler> clientList;

    public Server(int port) {
        this.port = port;
        this.userID = 0;
        clientList = new ArrayList<>();
        this.initialize();
    }

    public void initialize() {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }

        while (true) {
            try {
                socket = serverSocket.accept();

                messageFromClientToHandler = new DataInputStream(socket.getInputStream());
                messageFromHandlerToRecipient = new DataOutputStream(socket.getOutputStream());

                String userName = messageFromClientToHandler.readUTF();

                messageFromHandlerToRecipient.writeInt(userID);

                ClientHandler client = new ClientHandler(userID, userName, this, socket, messageFromClientToHandler, messageFromHandlerToRecipient);

                clientList.add(client);

                //Should set client.setUncaughtExceptionHandler();

                client.start();

                userID = userID + 1;

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

    public ServerSocket getServerSocket() {
        return serverSocket;
    }

    public Socket getSocket() {
        return socket;
    }

    public DataInputStream getMessageFromClientToHandler() {
        return messageFromClientToHandler;
    }

    public DataOutputStream getMessageFromHandlerToRecipient() {
        return messageFromHandlerToRecipient;
    }

    public int getPort() {
        return port;
    }

    public static int getUserID() {
        return userID;
    }

    public ArrayList<ClientHandler> getClientList() {
        return clientList;
    }

    public static void main(String[] args) {
        Server server = new Server(5050);
    }
}

客户端处理程序代码:

package AdvanceThreading.Server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.StringTokenizer;

public class ClientHandler extends Thread {

    private int clientID;
    private String clientName;
    private boolean loggedIn;

    private Socket socket;

    private Server server;

    private DataInputStream messageFromClientToHandler;
    private DataOutputStream messageFromHandlerToRecipient;


    public ClientHandler(int clientID, String clientName, Server server, Socket socket, DataInputStream messageFromClientToHandler, DataOutputStream messageFromHandlerToRecipient) {
        this.clientID = clientID;
        this.clientName = clientName;
        this.loggedIn = true;
        this.server = server;
        this.socket = socket;
        this.messageFromClientToHandler = messageFromClientToHandler;
        this.messageFromHandlerToRecipient = messageFromHandlerToRecipient;
    }

    @Override
    public void run() {

        String receivedFromClient;
        StringTokenizer tokenize = null;

        while (true) {
            try {
                receivedFromClient = messageFromClientToHandler.readUTF();

                System.out.println(receivedFromClient);

                tokenize = new StringTokenizer(receivedFromClient, "#");
                String recipient = tokenize.nextToken();
                int recipientID = Integer.parseInt(tokenize.nextToken());
                String message = tokenize.nextToken();

                //Need to handle exception of client not found.

                for (ClientHandler client : server.getClientList()) {
                    if (client.getClientID() == recipientID && client.isLoggedIn()) {
                        client.getMessageFromHandlerToRecipient().writeUTF(this.clientName + ": " + message);
                        break;
                    }
                }
            } catch (IOException e) {
                while (tokenize != null && tokenize.hasMoreTokens())
                    tokenize.nextToken();

                e.printStackTrace();
            }
        }
    }

    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    public int getClientID() {
        return clientID;
    }

    public Socket getSocket() {
        return socket;
    }

    public Server getServer() {
        return server;
    }

    public DataInputStream getMessageFromClientToHandler() {
        return messageFromClientToHandler;
    }

    public DataOutputStream getMessageFromHandlerToRecipient() {
        return messageFromHandlerToRecipient;
    }
}

如果使用终端的客户端(例如:CMD)出现错误,我想做的主要事情是我想捕获错误并处理它,并在同一个终端上恢复他的会话,这样他就不必重新连接到服务器。

【问题讨论】:

  • 旁注:有 IO 问题的终端会话可能会引发异常,在这种情况下,无法重用相同的终端会话
  • 那么,基本上由我来确保客户不会犯错?
  • 您可以通过添加运行时异常 try catch 块来轻松解决任何与转换相关的异常,我会在几秒钟内为您删除代码
  • 一旦线程终止(即未捕获的异常),它就无法恢复。在线程上运行的代码内部必须有逻辑以“处理错误并适当地继续”或在线程外部“启动新线程”。捕获异常不会“暂停”线程;相反,这只是与 if-something-failed-then 相同的标准流控制操作。

标签: java multithreading networking error-handling


【解决方案1】:

根据讨论,您可以使用 RuntimeException 捕获任何无效的相关数据异常:

  StringTokenizer tokenize = new StringTokenizer(receivedFromClient, "#");

        try {
            String recipient = tokenize.nextToken();

            int recipientID = Integer.parseInt(tokenize.nextToken());
            String message = tokenize.nextToken();
        } catch (RuntimeException e) {

            //ask client to resend the data
            continue
        }

【讨论】:

  • 谢谢老兄,我按照你说的做了,我在客户端处理程序的范围内处理了运行时异常。
猜你喜欢
  • 2019-06-15
  • 1970-01-01
  • 2010-09-10
  • 2010-10-02
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多