java 多次new DataOutputStream而不关闭,线程阻塞

我的系统需要与多个服务端建立通信连接,也就是建立多个socket用于长时间通信,然后我有一个静态方法可以通过传入参数socket向任意一个服务端发送数据,方法如下:pub... 我的系统需要与多个服务端建立通信连接,也就是建立多个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也被关闭了。面对这种情况,应该如何处理?如果不能避免可以怎样换个方式实现此功能
展开
 我来答
q神奇物种
2013-08-08 · TA获得超过304个赞
知道答主
回答量:38
采纳率:100%
帮助的人:25.4万
展开全部

你试试用这种方法:

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 这是这个类的完整一个例子(也是多用户聊天通讯的),你看看吧(不算太难)

百度网友b8678e2
2013-08-08 · TA获得超过693个赞
知道小有建树答主
回答量:309
采纳率:0%
帮助的人:163万
展开全部
为什么一定要套一个DataOutputStream?直接用socket的流写不行吗?是不是socket缓冲区满了啊?另一端有在实时读取吗?
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式