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

2025-05-22 21:29:35
推荐回答(2个)
回答1:

你试试用这种方法:

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;

/**
 * 服务线程类
 * 功能:控制数据的基本收发
 * 

编写时间: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> iter = CommonData.getClientThreadMap().entrySet().iterator();

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

回答2:

为什么一定要套一个DataOutputStream?直接用socket的流写不行吗?是不是socket缓冲区满了啊?另一端有在实时读取吗?