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

为什么在Java中,实例化顺序似乎对输入和输出流很重要?,java,objectinputstream,objectoutputstream,Java,Objectinputstream,Objectoutputstream,我有以下代码可以使用(请假设主机名和端口已初始化为其正确的值,并且消息是可序列化的类): 当我将ObjectOutputStream的实例化移动到ObjectOutputStream实例化之后立即发生时,我的应用程序的执行将无限期挂起: //Example 2 - client locks up Message message = new Message(); try(Socket serverSocket = new Socket(hostname, port)) { ObjectOu

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

当我将
ObjectOutputStream
的实例化移动到
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

的构造函数上,构建
ObjectOutputStream
会将头写入流。构造一个
ObjectInputStream
读取它。如果两端都先构造
ObjectInputStream
,则会出现死锁


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

构造
ObjectOutputStream
将头写入流。构造一个
ObjectInputStream
读取它。如果两端都先构造
ObjectInputStream
,则会出现死锁


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

如果我们去阅读
ObjectOutputStream的API文档

重要的部分是:

此构造函数将阻塞,直到相应的ObjectOutputStream 已写入并刷新标题


如果我们去阅读
ObjectInputStream的API文档

重要的部分是:

此构造函数将阻塞,直到相应的ObjectOutputStream 已写入并刷新标题


我想知道您是否正在经历
套接字内部的竞争。尝试在流的实例化之间放置一个Thread.sleep(100),看看它是否有效。如果是这样的话,那么你至少会知道这是一场比赛。这似乎不起作用。@pens-fan-69将睡眠添加到网络代码中只是一种货运邪教编程。它解决不了任何问题。你能进入构造器看看它挂在哪一行吗?@pens-fan-69你能读懂已经发布的两个正确答案吗?停止猜测?我想知道您是否正在经历
套接字内部的竞争。尝试在流的实例化之间放置一个Thread.sleep(100),看看它是否有效。如果是这样的话,那么你至少会知道这是一场比赛。这似乎不起作用。@pens-fan-69将睡眠添加到网络代码中只是一种货运邪教编程。它解决不了任何问题。你能进入构造器看看它挂在哪一行吗?@pens-fan-69你能读懂已经发布的两个正确答案吗?别再猜了?
//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();
}