簡體   English   中英

ConcurrentLinkedQueue $ Node實例增加並且JVM拋出OOM

[英]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。

幾個建議:

  1. 向您的應用程序添加更多的內存。 試試類似-Xmx2g東西
  2. 嘗試添加其他線程以從隊列中讀取
  3. 盡可能快地執行“使用緩沖區執行操作”
  4. 將“使用緩沖區執行某些操作”分解到自己的線程中(可能使用線程池),以防止其阻止從隊列中讀取更多內容

您是否已定時閱讀器服務中的所有內容以查看需要多長時間? 如果您確實將事物放到隊列中的速度比閱讀它們的速度快,那么您需要找到加快閱讀器速度的方法。 您的內存不足只是真正問題的副作用 問題是您沒有足夠快速地處理排隊的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM