【小白求教】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个回答

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

zkzk7410
zkzk7410 回复ljheee: 谢谢!
接近 3 年之前 回复
ljheee
ljheee 回复zkzk7410: 可以
接近 3 年之前 回复
zkzk7410
zkzk7410 大哥,能否这样理解: serversocket创建一个对象后,只能有一个serversocket.accpet()在工作,如果把它放入到线程中,会同时出现多个accept。就会锁死
接近 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问