zkzk7410 2017-04-26 14:12 采纳率: 68.8%
浏览 1818
已采纳

【小白求教】JAVA多线程跑ServerSocket内存逐渐爆满死机

第一个是教材上正确的代码,可以正常多线程运行的
主程序:
package com.server;
import java.io.*;
import java.util.*;
import java.net.*;
import com.bean.*;
import com.biz.ServerBiz;
public class MainServer {
private ServerSocket serverSocket;
private Socket socket;
private InputStream in;
private OutputStream out;

public MainServer() {
    //创建服务器的套接字
    try {
        serverSocket=new ServerSocket(8888);

        System.out.println("服务器已经启动.....");
        while(true){
            socket=serverSocket.accept();//监听并且接收客户端请求

            ServerBiz serverBiz=new ServerBiz(socket);

            Thread td=new Thread(serverBiz);//将serverBiz设置到线程中,每开一个客户端,会创建一个新的线程处理客户端的数据
            td.start();//开始
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
}



/**
 * @param args
 */
public static void main(String[] args) {
    new MainServer();

}

}

package com.biz;
import java.io.*;
import java.util.*;
import java.net.*;
import com.bean.*;

public class ServerBiz implements Runnable {

private Socket socket;
private InputStream in;
private OutputStream out;

public ServerBiz(Socket socket) {
    this.socket=socket;
    try {
        in=socket.getInputStream();
        out=socket.getOutputStream();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}



@Override
public void run() {
    try {
        /************接收***************************************/
        in=socket.getInputStream();
        ObjectInputStream objin=new ObjectInputStream(in);
        Users us=(Users) objin.readObject();
        int code=0;//状态码
        if(us!=null){
            if(us.getUname()!=null&&!us.getUname().trim().equals("")
                    &&us.getPasswd()!=null&&!us.getPasswd().trim().equals("")){
                System.out.println("账号:"+us.getUname());
                System.out.println("密码:"+us.getPasswd());
                code=1;//登陆成功!
            }
        }
        socket.shutdownInput();//结束接收
        /******************************************************/

        /*****向客户端发送响应***************************************/
        out=socket.getOutputStream();
        out.write(code);//向客户端发送状态码
        out.flush();
        socket.shutdownOutput();//结束输出
        /******************************************************/
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}

}

以上是教材正确的代码,
我奇怪为什么不能将 socket=serverSocket.accept() 写在runnable中的run方法中,于是我修改成了下面的代码,可是这个是不能正常运行的。
先打开任务管理器,再运行这个程序,可以看到内存在很短的时间内逐渐爆满,从而导致电脑无法使用

主程序:
package com.server;

import java.net.*;
import java.io.*;

import com.bean.Users;
import com.biz.ServerBiz;

public class MainServer {
private ServerSocket ss;

public MainServer() {

        try {
            ss = new ServerSocket(8888);
            System.out.println("服务器已经启动......");
            /************************ 客户端发送来的消息 **************************/
            while (true) {

                ServerBiz sb=new ServerBiz(ss);
                Thread t=new Thread(sb);
                t.start();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


}

public static void main(String[] args) {
    new MainServer();
}

}

下面是设置的Runnable
package com.biz;
import java.net.*;
import java.io.*;

import com.bean.Users;

public class ServerBiz implements Runnable {
private ServerSocket ss;

public ServerBiz(ServerSocket ss) {

    this.ss = ss;
}


@Override
public void run() {
    try {
        Socket sk = ss.accept();
        InputStream ips = sk.getInputStream();
        ObjectInputStream objectin = new ObjectInputStream(ips);
        Users user = new Users();
        user = (Users) objectin.readObject();
        int code = 0;
        if (user != null && user.getPassword() != null
                && user.getUname() != null
                && !user.getPassword().trim().equals("")
                &&!user.getUname().trim().equals("")) {
            System.out.println("用户名:" + user.getUname());
            System.out.println("密码:" + user.getPassword());
            code = 1;
        }
        sk.shutdownInput();
        /**************************************************************/

        /************************ 向客户端发送的消息 **************************/
        OutputStream ops = sk.getOutputStream();
        ops.write(code);
        ops.flush();
        sk.shutdownOutput();
        /**************************************************************/
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

(本来还有个client端,这里忽略)

求大神指点什么将 socket=serverSocket.accept() 写在Runnable中 ,运行后就死机啊,非常感谢啊!

  • 写回答

1条回答 默认 最新

  • ljheee 2017-04-26 14:33
    关注

    不能将 socket=serverSocket.accept() 写在runnable中的run方法中,
    serverSocket.accept() 是服务器接收到客户端连接,如果写在runnable中的run方法中,那意思就是——每一个子线程运行run方法时们都会serverSocket.accept()尝试去监听8888端口,

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 求数学坐标画圆以及直线的算法
  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决