java 多次new DataOutputStream而不关闭,线程阻塞
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 多次new DataOutputStream而不关闭,线程阻塞相关的知识,希望对你有一定的参考价值。
我的系统需要与多个服务端建立通信连接,也就是建立多个socket用于长时间通信,然后我有一个静态方法可以通过传入参数socket向任意一个服务端发送数据,方法如下:
public static void sendTCP(Socket socket,byte[] byteArr)
if(!socket.isClosed())
DataOutputStream os = null;
try
os = new DataOutputStream(socket.getOutputStream());
os.write(byteArr);
os.flush();
catch(SocketException e)
e.printStackTrace();
catch(Exception e)
e.printStackTrace();
现在问题在于,上面的静态方法中DataOutputStream每次用完之后都未关闭。我在一个线程中循环调用该方法,长时间高频率的调用后,数据就在也发布出去了。但是线程无异常,系统无异常,只是数据不能在发出去了,调用该方法的线程栈信息显示:
"@ReportSendThread" daemon prio=6 tid=0x492b3800 nid=0x1bf8 runnable [0x4a75f000..0x4a75fc98]
java.lang.Thread.State: RUNNABLE
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.DataOutputStream.write(DataOutputStream.java:90)
- locked <0x091aff20> (a java.io.DataOutputStream)
at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
at com.pq.communicate.frontcommunicate.util.IEC103.mainMethod.Encode103.sendTCP(Encode103.java:601)
at com.pq.communicate.frontcommunicate.util.IEC103.mainMethod.ReportSendThread.run(ReportSendThread.java:76)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- None
现在大概知道问题的所在,可能是DataOutputStream每次实例化后都没关闭。但我试过关闭DataOutputStream,但关闭后对应的socket也被关闭了。面对这种情况,应该如何处理?如果不能避免可以怎样换个方式实现此功能
你试试用这种方法:
package chat.server.controller;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;
import java.util.Map.Entry;
import chat.server.common.CommonData;
import chat.server.controller.MessageTypeEnum;
import chat.server.model.biz.ChatHandleBiz;
import chat.server.model.biz.LoginHandle;
/**
* 服务线程类
* 功能:控制数据的基本收发
* <p>编写时间:2013-06-06
*
* @author 财俊
*
*/
public class ServerThread extends Thread
private Socket socket = null;
private DataInputStream dis = null;
private DataOutputStream dos = null;
private String separatorStr = ""; // 消息分隔符
private boolean isListen = false;
private String clientName = ""; // 该线程服务的客户端用户名
public ServerThread(Socket socket_)
try
this.socket = socket_;
// 初始化消息定界符
separatorStr = ":::";
// 初始化输入输出流
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
catch(IOException e)
e.printStackTrace();
/**
* 向除拥有本实例以外的所有用户发送广播消息
*/
public void broadcast(String msgStr)
// 遍历在线用户表
Iterator<Entry<String, ServerThread>> iter = CommonData.getClientThreadMap().entrySet().iterator();
while (iter.hasNext())
Entry<String, ServerThread> entry = (Entry<String, ServerThread>) iter.next();
ServerThread clientThread = (ServerThread) entry.getValue();
if (clientThread != this)
clientThread.sendData(msgStr);
// String key = entry.getKey().toString();
/**
* 向该客户端发送消息
*
* @param socket_
* @param msgStr
*/
public void sendData(String msgStr_)
try
dos.writeUTF(msgStr_);
catch(IOException e)
e.printStackTrace();
/**
* 获取本实例的socket对象
*
* @return
*/
public Socket getSocket()
return this.socket;
/**
* 设置是否断续监听
* @param value
*/
public void setListen(boolean value)
this.isListen = value;
@Override
public void run()
try
// 消息内容
String msgStr = "";
// 分隔符在字符串中的位置
int separatorIndex = 0;
// 是否接收消息
isListen = true;
while (isListen)
// 接收消息
msgStr = dis.readUTF();
// 确定分隔符在字符串中的位置
separatorIndex = msgStr.indexOf(separatorStr);
// 提取消息类型
MessageTypeEnum msgType = MessageTypeEnum.valueOf(msgStr.substring(0, separatorIndex));
switch (msgType)
/***************** 初始化客户信息 ******************/
case Login:
// msgStr 格式为msgtype:::name:::sex
clientName = msgStr.substring(separatorIndex + 3).split(":::")[0];
// 交给biz层处理
LoginHandle.getLoginHandle().clientLoginHandle(msgStr.substring(separatorIndex + 3), this);
break;
/***************** 群聊消息 ******************/
case GroupChat:
// 交给biz层处理
ChatHandleBiz.getChatHandleBiz().groupChatHandle(msgStr.substring(separatorIndex + 3));
break;
/***************** 一对一聊天消息 ******************/
case SingleChat:
// 交给biz层处理
ChatHandleBiz.getChatHandleBiz().singleChatHandle(msgStr.substring(separatorIndex + 3));
break;
default:
break;
catch(SocketException e)
try
// 处理用户下线
LoginHandle.getLoginHandle().ClientOffLineHandle(clientName, this);
// 关闭流和连接
dos.flush();
dos.close();
dis.close();
socket.close();
catch(IOException e1)
e1.printStackTrace();
// e.printStackTrace();
catch(IOException e)
e.printStackTrace();
不知道你能不能看懂这个类,大概意思是 用一个类保存一个socket 和 和socket有关的东西,一个用户就一个线程,(在线程中new 出这个类,同时也保持一个socket)
download.csdn.net/detail/tangcaijun/5556391 这是这个类的完整一个例子(也是多用户聊天通讯的),你看看吧(不算太难)
以上是关于java 多次new DataOutputStream而不关闭,线程阻塞的主要内容,如果未能解决你的问题,请参考以下文章