2013-07-16 158 views
0

我正在使用libgdx作爲我正在寫的遊戲,其中有另一個線程需要更新圖形線程。由於libgdx不是線程安全的(故意),我得到了崩潰,我允許其他線程直接修改圖形線程中的變量。是否有可能重新使用包含閉包的Runnable

libgdx docs建議類似於下面的代碼。它基本上是一個包含傳入信息的閉包,當圖形線程到達時,它將被處理。

我修改了它來聲明偵聽器之外的可運行內存,希望我可以避免垃圾回收,但是對我而言,現在我可能已經創建了競爭條件,其中runnable可能會被覆蓋圖形線程消耗以前的信息?

到目前爲止,我已經能夠避免其他地方的垃圾收集,而且我的遊戲也利用Android中的低延遲音頻綁定,因此垃圾收集實際上是我的敵人。

有什麼建議嗎?

private Runnable runnable; 
private SomeListener listener = new SomeListener() { 
    @Override 
    public void messageIn(final String source, final String s, final Object... l) { 
     runnable = new Runnable() { 
      @Override 
      public void run() { getWorkspace().messageIn(s,l); } 
     }; 
     Gdx.app.postRunnable(runnable); 
    } 

};

回答

1

我修改了它來聲明偵聽器之外的runnable,希望我可以避免垃圾回收,但是現在我可能已經創建了一個競爭條件,其中runnable可以被先前覆蓋到圖形線程消耗以前的信息?

是的,這肯定會發生。此外,您不能使用ThreadLocal,因爲它將處理回調與可運行的不同線程。

你可以做的是創建Runnable類的BlockingQueue。運行方法結束後,Runnable可以將自己置於BlockingQueue的末尾以便重新使用。當調用messageIn(...)方法時,它將調用queue.poll(),並且只有在隊列中沒有任何方法時才創建一個新方法。這會增加內存同步但降低GC帶寬。它可能不會獲得太多收益。

您可能會考慮運行內存分析器,以確保這是您應該將重點集中於嘗試降低內存使用率的地方。

+0

我的消息很小(關鍵字和一個浮點或兩個),所以這可能是一個不錯的選擇。我假設內存同步成本與消息的大小成正比?而且..哦,如果我不在新的Runnable中,我該如何讓我的閉包工作? –

+0

同步成本可能是線性成本 - 並未考慮到消息大小@DarenSchwenke。關閉的地方在哪裏?這是一個匿名課程,但我沒有看到任何關閉。 – Gray

+0

使用s和l from messageIn通過getWorkspace()調用runnable run。messageIn(s,l);可能會讓人困惑。外部messageIn是我另一個線程中的一個方法,inner是圖形線程中的一個方法。在新的Runnable權利聲明中使用時,在外部進行最終決策時會創建一個閉包......或者我誤會了。 (約6個月前開始java的perl傢伙) –

1

由於您正在開發遊戲,我建議您將所有消息發佈到隊列中,然後根據需要在遊戲循環中消耗。

+0

對,但是如何在不導致內容被垃圾收集的情況下創建消息?將message中的runnable聲明完成你的建議,但會導致垃圾回收。 –

+0

雖然它的引用在隊列中,但不會被收集。從隊列中刪除它,消耗它,然後GC可能會刪除ref。 –

+0

我試圖在這裏完全避免GC。我現在使用這種方法的GC每隔30秒左右2-5ms,但由於低延時音頻要求,我只有6ms的總可用時間,這太多了。 postRunnable()是我可以正確地對圖形線程進行更改的時間的方法,所以問題變成了如何設置並拆除沒有GC的Runnable。我真正負擔得起任何GC的唯一時間是在屏幕更改期間或用戶暫停音頻輸入/輸出時。我做出這種事情的簡單方法是一直集中並重新使用所有東西,直到此時爲止 –

相關問題