创建 ObjectInputStream 时线程挂起 [英] Thread hangs when creating ObjectInputStream

查看:38
本文介绍了创建 ObjectInputStream 时线程挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的服务器端有以下代码:

public class ClientThread extends Thread
{
Socket clientSocket;

DataInputStream dis;
ObjectInputStream ois;
DataOutputStream dos;

public ClientThread(Socket acceptedSocket)
{
    clientSocket = acceptedSocket;

    try
    {
        dis = new DataInputStream(clientSocket.getInputStream());
        ois = new ObjectInputStream(clientSocket.getInputStream()); // HANGS HERE
        dos = new DataOutputStream(clientSocket.getOutputStream());
    }
    catch (Exception e)
    {
        System.out.println("ClientThread " + e.getMessage());
    }
}   

其余课程省略

为什么我的应用程序在调用套接字输入流两次时会死机,而没有抛出异常?

Why does my application freeze when calling the socket inputstream twice, without throwing an exception?

是的,我可以将输入流保存到 InputStream 变量并使用该变量来获取所需的输入流类型,但我很好奇为什么从套接字调用两次时它会挂起?

有什么区别?被调用两次不会改变什么?

What's the difference? Being called twice doesn't change anything?

即使将输入流保存到 InputStream 变量并使用该变量来获取所需的输入流(DataInputStream 和 ObjectInputStream),它在多次调用时仍然挂起?

Even when saving the inputstream to an InputStream variable and using that variable to get the desired inputstream (DataInputStream and ObjectInputStream) it still hangs when called more than once?

示例:

public class ClientThread extends Thread
{
Socket clientSocket;

InputStream is;
DataInputStream dis;
ObjectInputStream ois;
DataOutputStream dos;

public ClientThread(Socket acceptedSocket)
{
    clientSocket = acceptedSocket;

    try
    {
        is = clientSocket.getInputStream();
        dis = new DataInputStream(is);
        ois = new ObjectInputStream(is); // STILL HANGS HERE
        dos = new DataOutputStream(clientSocket.getOutputStream());
    }
    catch (Exception e)
    {
        System.out.println("ClientThread " + e.getMessage());
    }
}   

其余课程省略

客户端代码:

public class LoginLogic_Callable implements Callable<String>
{
Socket socket;
String actionString;
String username;
String password;

public LoginLogic_Callable(Socket sentSocket, String sentUsername, String sentPassword)
{
    socket = sentSocket;
    username = sentUsername;
    password = sentPassword;
}

@Override
public String call() throws Exception 
{
    String userLoginStatus = null;

    try
    {
        DataOutputStream loginUserData = new DataOutputStream(socket.getOutputStream()); 
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        DataInputStream dis = new DataInputStream(socket.getInputStream());

        String[] loginUserInfo = new String[2];

        loginUserInfo[0] = username;
        loginUserInfo[1] = password;

        loginUserData.writeUTF("userlogin");
        oos.writeObject(loginUserInfo);
        loginUserData.flush();
        oos.flush();

        userLoginStatus = dis.readUTF();

        loginUserData.close();
        oos.close();
        dis.close();
    }
    catch (Exception e)
    {
    }   

    return userLoginStatus;
}
}

推荐答案

仅调用 getInputStream() 不是阅读",也不会导致此问题.你可以通过调用它十次,或者构造十个 DataInputStreams 来证明它.导致问题的是 ObjectInputStream 的构造,您可以通过完全删除 DataInputStream 来证明这一点,无论如何您都应该这样做: 见下文.

Just calling getInputStream() isn't 'reading', and it doesn't cause this problem. You can prove that by calling it ten times, or constructing ten DataInputStreams round it. It is the construction of the ObjectInputStream that is causing the problem, and you can prove that by removing the DataInputStream altogether, which you should do anyway: see below.

您正在创建一个 ObjectInputStream.ObjectInputStream 的构造函数读取由ObjectOutputStream 的构造函数写入的流头.由于这不会发生在这段代码中,并且可能也不会发生在对等点上,因此它会永远阻塞.

You're creating an ObjectInputStream. The constructor of ObjectInputStream reads a stream header that is written by the constructor of ObjectOutputStream. As that isn't happening in this code, and presumably not at the peer either, it blocks forever.

出于同样的原因,您必须先创建 ObjectOutputStream,然后再创建 ObjectInputStream,否则会再次出现死锁.

For the same reason, you must create the ObjectOutputStream first, before the ObjectInputStream, otherwise again you will have a deadlock.

这里似乎有一些计划在同一个套接字上使用两种流.不要那样做.这是行不通的,也没有必要,因为对象流除了对象的读写方法之外,还有与数据流相同的方法.

There seems to be some plan here to use two kinds of stream on the same socket. Don't do that. It won't work, and it isn't necessary, as the object streams have all the same methods as the data streams, in addition to the object reading and writing methods.

EDIT 现在您已经发布了您的客户端代码,发生的情况是客户端将 ObjectOutputStream 的创建推迟到 call()代码>被调用.它应该在该类的构造函数中创建.否则你的服务器端构造函数会阻塞,直到 call() 在客户端被调用.而且您仍然需要摆脱多余的流.

EDIT Now that you've posted your client code, what is happening is that the client is deferring creation of the ObjectOutputStream until call() is called. It should be created in the constructor of that class. Otherwise your server side constructor blocks until call() is called at the client. And you still need to get rid of the redundant streams.

这篇关于创建 ObjectInputStream 时线程挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆