Java 创建ObjectInputStream时线程挂起
我的服务器上有以下代码:Java 创建ObjectInputStream时线程挂起,java,stream,Java,Stream,我的服务器上有以下代码: public class ClientThread extends Thread { Socket clientSocket; DataInputStream dis; ObjectInputStream ois; DataOutputStream dos; public ClientThread(Socket acceptedSocket) { clientSocket = acceptedSocket; try { di
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());
}
}
省略了班上的其他部分
为什么我的应用程序在两次调用socket inputstream而不引发异常时会冻结
是的,我可以将inputstream保存到一个inputstream变量中,并使用该变量来获得所需的inputstream类型,但我很好奇,当从套接字调用两次时,为什么它会挂起
有什么区别?被叫两次也不会改变什么
编辑:即使将inputstream保存到inputstream变量并使用该变量获取所需的inputstream(DataInputStream和ObjectInputStream),在多次调用时它仍然挂起 例如:
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;
}
}
公共类LoginLogic\u Callable实现可调用
{
插座;
字符串actionString;
字符串用户名;
字符串密码;
公共LoginLogic_可调用(套接字sentSocket、字符串sentUsername、字符串sentPassword)
{
插座=插座;
用户名=用户名;
密码=密码;
}
@凌驾
公共字符串调用()引发异常
{
字符串userLoginStatus=null;
尝试
{
DataOutputStream loginUserData=新的DataOutputStream(socket.getOutputStream());
ObjectOutputStream oos=新的ObjectOutputStream(socket.getOutputStream());
DataInputStream dis=新的DataInputStream(socket.getInputStream());
String[]loginUserInfo=新字符串[2];
loginUserInfo[0]=用户名;
loginUserInfo[1]=密码;
loginUserData.writeUTF(“用户登录”);
oos.writeObject(loginUserInfo);
loginUserData.flush();
oos.flush();
userLoginStatus=dis.readUTF();
loginUserData.close();
oos.close();
dis.close();
}
捕获(例外e)
{
}
返回userLoginStatus;
}
}
仅调用getInputStream()
不是“读取”,也不会导致此问题。您可以通过十次调用它,或者构造十个DataInputStreams
来证明这一点。问题是由ObjectInputStream
的构造引起的,您可以通过删除DataInputStream
来证明这一点,您无论如何都应该这样做:见下文
您正在创建一个ObjectInputStream
。ObjectOutputStream
的构造函数读取由ObjectOutputStream的构造函数编写的流头。由于这在代码中没有发生,并且可能在对等端也没有发生,所以它会永远阻塞
出于同样的原因,必须先创建ObjectOutputStream
,然后再创建ObjectInputStream
,否则将再次出现死锁
这里似乎有一些计划在同一个套接字上使用两种流。不要那样做。它不会工作,也没有必要,因为除了对象读取和写入方法之外,对象流与数据流具有所有相同的方法
编辑现在,您已经发布了客户端代码,现在发生的情况是客户端正在推迟创建ObjectOutputStream
,直到调用call()
。它应该在该类的构造函数中创建。否则,服务器端构造函数将阻塞,直到在客户端调用call()
。您仍然需要消除冗余流。我知道在android中,东西有时会挂起,但使用asynctask可以解决这个问题。不知道java中异步任务的名称。我想这不是问题,只是一个评论。如果你编辑,你似乎没有读过我的答案。请发布相关的客户端代码。添加了客户端代码。好的,现在请查看编辑我的答案。这没有意义。。。所以你是说我必须在创建ObjectInputStream之前创建ObjectOutputStream,即使在这种情况下我永远不会使用ObjectOutputStream。@Birdman如果你永远不会使用ObjectOutputStream,那么你打算什么时候使用ObjectOutputStream?如果输出流不发送对象,则无法接收输入流中的对象。客户端(对等方)有一个ObjectOutputStream,服务器(此处就是这种情况)有一个ObjectInputStream来接收对象。那怎么了?它不仅有意义,而且在Javadoc中有文档记录。如果对等方正在创建ObjectOutputStream,那么它必须在创建ObjectInputStream之后创建,这会导致死锁,正如我前面所说的那样。@Alex,这不符合要求。您可以只向一个方向发送对象,也可以向两个方向发送对象。