为什么实例化的顺序似乎对Java中的输入和输出流很重要?

时间:2015-06-10 20:16:23

标签: java objectinputstream objectoutputstream

我有以下代码可以使用(请假设主机名和端口已初始化为其正确的值,并且该Message是可序列化的类):

//Example 1 - everything works as expected
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
    ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());                  
    outStream.writeObject(message);
    outStream.flush();

    ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());
    Object response = inStream.readObject();
}

当我将ObjectInputStream的实例化移动到ObjectOutputStream实例化后立即发生时,我的应用程序的执行会无限期地挂起:

//Example 2 - client locks up
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
    ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());                  
    ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());

    outStream.writeObject(message);
    outStream.flush();

    Object response = inStream.readObject();
}

我正在寻找一个很好的解释,为什么第二个例子会一直锁定,第一个例子似乎没有任何障碍。奇怪的是,如果我在第二个例子中在客户端和服务器上使用调试器(Eclipse调试器),我看到消息将通过服务器,因此正在执行writeObject()调用。但是,在客户端中,调试器会卡在ObjectInputStream的构造函数上。

2 个答案:

答案 0 :(得分:3)

如果我们开始阅读ObjectInputStream constructor

的API文档

重要的部分:

  

此构造函数将阻塞,直到相应的ObjectOutputStream为止   写了并刷了头。

答案 1 :(得分:1)

构造ObjectOutputStream将标头写入流。构造ObjectInputStream读取它。如果两端首先构造ObjectInputStream,那么您将陷入僵局。

解决方案:首先在两端构建ObjectOutputStream,以确保它不会发生。