Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以重复使用包含闭包的可运行闭包_Java_Android_Multithreading_Garbage Collection_Libgdx - Fatal编程技术网

Java 是否可以重复使用包含闭包的可运行闭包

Java 是否可以重复使用包含闭包的可运行闭包,java,android,multithreading,garbage-collection,libgdx,Java,Android,Multithreading,Garbage Collection,Libgdx,我正在编写一个游戏,我有另一个线程需要更新图形线程。由于libgdx不是线程安全的(故意的),并且我允许另一个线程直接修改图形线程中的变量,所以我遇到了崩溃 建议使用类似于以下代码的代码。它基本上是一个包含传入信息的闭包,然后在图形线程到达它时对其进行处理 我修改了它,在侦听器外部声明runnable,希望可以避免垃圾收集,但我突然想到,我现在可能已经创建了一个争用条件,在图形线程消耗之前可以覆盖runnable 到目前为止,我已经能够在其他地方避免垃圾收集,我的游戏也利用了Android中的低

我正在编写一个游戏,我有另一个线程需要更新图形线程。由于libgdx不是线程安全的(故意的),并且我允许另一个线程直接修改图形线程中的变量,所以我遇到了崩溃

建议使用类似于以下代码的代码。它基本上是一个包含传入信息的闭包,然后在图形线程到达它时对其进行处理

我修改了它,在侦听器外部声明runnable,希望可以避免垃圾收集,但我突然想到,我现在可能已经创建了一个争用条件,在图形线程消耗之前可以覆盖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);
    }

})

由于您正在开发一个游戏,我建议您将所有消息发布到一个队列中,然后根据需要在游戏循环中使用这些消息

我修改了它,在侦听器外部声明runnable,希望可以避免垃圾收集,但我突然想到,我现在可能已经创建了一个争用条件,在图形线程消耗之前可以覆盖runnable

是的,这肯定会发生。此外,您不能使用
ThreadLocal
s,因为处理回调和可运行回调的线程将不同

您可以做的是创建
Runnable
类的
BlockingQueue
。一旦run方法完成,
Runnable
可以将自己放在
BlockingQueue
的末尾,以便重用。调用
messageIn(…)
方法时,它将调用
queue.poll()
,并且仅当队列中没有队列时才创建一个新的队列。这将增加内存同步,但降低GC带宽。这可能不会给你带来太多好处


您可以考虑运行内存剖析器,以确保这是您应该集中精力重构以降低内存使用量的地方。

是的,但是如何创建消息而不使内容稍后被垃圾收集?将runnable声明放入messageIn可以完成您的建议,但会导致垃圾收集。当它的引用在队列中时,将不会收集它。从队列中删除它,使用它,然后GC可能会删除ref。我目前使用这种方法的GC是每30秒2-5毫秒左右,但由于低延迟音频要求,我总共只有6毫秒的可用时间,这太多了。postRunnable()是我可以用来正确计时对图形线程所做更改的方法,因此问题变成了如何在没有GC的情况下设置和删除这些可运行程序。我唯一能真正负担得起GC的时间是在屏幕更改期间或用户暂停音频输入/输出时。我实现这一点的简单方法是将所有内容集中起来并重新使用,直到创建一个可运行文件列表,将新的文件永远添加到列表中,在合适的时间清理,从列表中删除已完成的进程,这应该可以避免GC。如果你正在做一个游戏,并且应该将东西发布到游戏线程(无限循环),你应该使用一个队列,并在正确的步骤中使用数据(可能是proccessLogicas(长正常运行时间)os somthing类似)我的消息很小(关键字和一个或两个浮点),因此这可能是一个好的选择。我假设内存同步成本与消息的大小成正比?和。。哦如果我不在新的可运行状态下,如何使闭包工作?同步成本可能是一个线性成本,而不是消息@DarenSchwenke的大小。关闭从哪里来?这是一个匿名类,但我没有看到任何闭包;可能有点困惑。外部messageIn是我的另一个线程中的一个方法,内部messageIn是图形线程中的一个方法。当在新的可运行权限声明中使用时,在外部将它们设置为final本质上创建了一个闭包。。。还是我错了。(大约6个月前开始使用java的perl家伙)不,闭包是java7 thang。这只是一个参数。DarenSchwenke没有闭包。让它们成为最终的仅仅意味着它们的价值无法改变。也许我当时考虑过了。那么,如果我像你说的那样创建了一个Runnable队列,那么如何在每个Runnable中的run方法中更改s,l的值,而不使用新的?扩展Runnable并将其作为私有变量添加?我假设“新”是导致GC的原因。如果我错了,请纠正我。