我有一个多线程Java Web服务器,它接受来自客户端的请求。
RAM中的每个请求都为此请求分配内存,但在套接字关闭后不会清除它。只有在重新启动Web服务器后才会进行清理。
如果是内存泄漏,那么它可以在哪部分代码中出现?
我的代码:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(80)) {
Socket socket = server.accept();
while (true) {
new Thread(new Client(socket)).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Client implements Runnable {
private Socket socket;
Client(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
System.out.println("run");
} finally {
try {
socket.close();
System.out.println("Socket closed: " + socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
答案 0 :(得分:2)
为每个传入连接启动一个新线程是非常低效的,可能就是泄漏内存。
正确的方法是使用具有固定数量的线程的线程池,这些线程可以重复使用。
还值得指出的是,线程消耗大量本机内存(在Java堆之外)而在堆内存上消耗很少,因此不会触发垃圾收集,而垃圾收集又会调用终结器来释放本地方。
编辑: 代码也没有做你认为它做的事情。在循环之外接受意味着代码只会为agian上的同一连接启动线程,而不是每个连接的新线程。
答案 1 :(得分:0)
在while(true)
循环中创建线程绝不是一个好主意
默认情况下,创建的每个Thread都将分配; 1mb用于64位jvm,128kb用于32位jvm用于其堆栈(这是针对linux os,其他细节here)。尝试ExecutorService
来做这类事情。线程是宝贵的资源。