2013-07-16 105 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的唯一时间是在屏幕更改期间或用户暂停音频输入/输出时。我做出这种事情的简单方法是一直集中并重新使用所有东西,直到此时为止 –

相关问题