【发布时间】:2015-05-20 15:49:55
【问题描述】:
我正在尝试构建服务器,但线程池的使用引入了内存泄漏,导致我的堆溢出。
我的服务器从主线程创建了两个主线程,Acceptor 和 Consumer。我是 JProfiler 的新手,但它似乎非常清楚地将我指向下面的代码(Acceptor)作为罪魁祸首。
Acceptor 线程接受来自客户端的新连接。在接受调用后,线程池中的新线程用于处理连接。
public class AcceptorThread implements Runnable{
LinkedBlockingQueue<LinkedList<Log_Message>> queue = null;
public AcceptorThread(LinkedBlockingQueue<LinkedList<Log_Message>> queue){
this.queue = queue;
}
@Override
public void run() {
ExecutorService acceptors = Executors.newCachedThreadPool();
ServerSocket socket = null;
try {
socket = new ServerSocket(44431);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(!init_LogServer.isStopped()){
Socket connectionSocket = null;
try {
connectionSocket = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
init_LogServer.addList();
System.out.println("Accepted New List: " + init_LogServer.getListCount());
Runnable worker = new List_Acceptor(connectionSocket, queue);
acceptors.execute(worker);
}
}
}
线程池中的新线程接收到一个对象的链表,这个链表被加入到队列中,线程就完成了。我的理解是,在完成下面的代码后,线程将终止,下面的对象将被 GC 收集,线程将重新进入线程池以供重用。我看不到任何明显的小内存泄漏,所以我猜测会发生什么情况是 GC 永远不会收集下面的类导致堆构建,对吗?将接收到的列表添加到队列后,如何销毁以下对象?
public class List_Acceptor implements Runnable{
Socket socket = null;
private LinkedList<Log_Message> lmList = null;
private LinkedBlockingQueue<LinkedList<Log_Message>> queue = null;
private String dumpMessage = null;
public List_Acceptor(Socket socket, LinkedBlockingQueue<LinkedList<Log_Message>> queue){
this.queue = queue;
this.socket = socket;
}
@Override
public void run() {
ObjectInputStream input = null;
try {
input = new ObjectInputStream(socket.getInputStream());
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
Object received = null;
try {
received = input.readObject();
} catch (ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
lmList = (LinkedList<Log_Message>) received;
} catch (Exception e1) {
//e1.printStackTrace();
System.out.println("Received DumpLog");
dumpMessage = (String) received;
System.out.println("Dump: "+dumpMessage);
init_LogServer.stop();
e1.printStackTrace();
}
//close socket
try {
socket.close();
input.close();
} catch (IOException e2) {e2.printStackTrace();}
try {
queue.put(lmList);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
编辑:我了解到,当一个对象/类通过线程实例化时,就像我对线程池所做的那样,GC 被限制清理该对象。这似乎是内存泄漏的可能原因,并且可能是我的问题。考虑到这一点,明天我将重新设计,以便 AcceptorTread 执行将接收到的列表放入队列的必要步骤,它应该会更慢,但会防止堆问题。那有意义吗?
【问题讨论】:
标签: java multithreading memory-leaks garbage-collection jprofiler