[英]ConcurrentLinkedQueue$Node instances grow and JVM throws OOM
我在生產者-消費者方案中使用ConcurrentLinkedQueue。 我的生產者是應用程序中所有方法都調用的Singleton:Producer.getInstance()。add(“ foo”); add()方法調用ConcurrentLinkedQueue offer方法。
public void add(String message) {
myQueue.offer(message);
}
否則,我的消費者將在另一個線程中運行,並僅在生產者內部的ConcurrentLinkedQueue上調用poll方法。
編輯:
在if(((buffer = myQueue.poll())!= null){}之間添加代碼
CRActiveMQProducer是一個Singleton,用於初始化與我的ActiveMQ服務器的連接並使用send()方法發送消息。
private StringBuffer stringBuffer = new StringBuffer();
public void run() {
while(condition) {
String buffer = null;
if ((buffer = myQueue.poll()) != null) {
stringBuffer.append(buffer);
numberMessage++;
if (numberMessage >= 10000) {
CRActiveMQProducer.getInstance().send(stringBuffer.toString());
stringBuffer = stringBuffer.delete(0, stringBuffer.length());
numberMessage = 0L;
}
}
}
}
我將Producer add()方法稱為5000萬次(是的,它很大,但這只是應完成的調用次數的2.5%)
無論如何,我遇到了OutOfMemory異常,我嘗試使用VisualVM讀取堆轉儲,我發現此OOM是由大量ConcurrentLinkedQueue $ Node實例(超過3000萬個)引起的。 我認為我為每個offer()或poll()方法調用都有一個新節點,但不是100%確定(無法加載完整的堆轉儲...)。
您是否認為這是ConcurrentLinkedQueue的正常行為? 還是我做錯了什么? 謝謝!
隊列顯然必須存儲您放入隊列中的所有元素,並且它使用相互鏈接的節點來實現。 這就是鏈接隊列的原理。 生產者生產Itels的速度過快,而消費者沒有時間消費它們,因此最終,您得到了OOM。
您應該考慮使用綁定的BlockingQueue:當隊列包含太多元素時,它將強制生產者線程阻塞,從而避免了OOM。
幾個建議:
-Xmx2g
東西 您是否已定時閱讀器服務中的所有內容以查看需要多長時間? 如果您確實將事物放到隊列中的速度比閱讀它們的速度快,那么您需要找到加快閱讀器速度的方法。 您的內存不足只是真正問題的副作用 。 問題是您沒有足夠快速地處理排隊的工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.