计划的未来可能会导致内存泄漏? [英] Can a scheduled future cause a memory leak?

查看:264
本文介绍了计划的未来可能会导致内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我已经在我的Andr​​oid动态壁纸的内存泄漏。每当我旋转屏幕,内存的垃圾量由50KB收集增大,不回去了。我想这可能是由计划未来造成的,所以我要present的场景,看看是否是这种情况。

I think I have a memory leak in my Android live wallpaper. Whenever I rotate the screen, the amount of memory garbage collected increases by 50kb and doesn't go back down. I think it may be caused by a scheduled future, so I'm going to present a scenario to see if that's the case.

假设你有一个类(姑且称之为富),有以下成员。

Let's say you have a class (let's call it Foo) that has the following members.

private ScheduledFuture<?> future;
private final ScheduledExecutorService scheduler = Executors
        .newSingleThreadScheduledExecutor();

private final Runnable runnable = new Runnable() {
    public void run() {
        // Do stuff
    }
};

现在你设置一个预定的未来

And now you set a scheduled future

future = scheduler.scheduleAtFixedRate(runnable, delay, speed,
                TimeUnit.MILLISECONDS);

未来有一个参考可运行,并且可运行持有引用父Foo对象。我不知道,如果是这样的话,但可能这个事实意味着,如果没有在程序中持有的引用,美孚,垃圾收集器仍无法收集,因为有计划的未来?我不是在多线程太好,所以我不知道,如果code我展示手段的计划任务将活得比的对象,这意味着它最终不会被垃圾收集。

The future holds a reference to the runnable, and the runnable holds a reference to the parent Foo object. I'm not sure if this is the case, but could this fact mean that if nothing in the program holds a reference to Foo, the garbage collector still cannot collect it because there is a scheduled future? I'm not too good at multithreading, so I don't know if the code I've shown means the scheduled task will live longer than the object, meaning it won't end up being garbage collected.

如果这种情况将不会被垃圾收集导致preventing富,我只需要被告知,有一个简单的解释。如果是这样prevent富被垃圾收集,那么如何解决呢?做必须做的 future.cancel(真正的);未来= NULL; ?是未来= NULL 部分不必要的?

If this scenario will not result in preventing Foo from being garbage collection, I just need to be told that with a simple explanation. If it does prevent Foo from being garbage collected, then how do I fix it? Do have to do future.cancel(true); future = null;? Is the future = null part unnecessary?

推荐答案

  • 无论你的运行方法依赖于封闭类,因此不能独立生活。在这种情况下,我看不出你可以有你的 gc'ed,并保持你的可运行的活着由执行人运行
  • 运行方法是静态的,即它不依赖于你的类的状态在这种情况下,你可以把静态的,它会prevent您所遇到的问题。

  • Either your run method relies on the enclosing Foo class and therefore can't live independently. In that case I don't see how you could have your Foo gc'ed and keep your runnable "alive" to be run by the executor
  • or your run method is static in the sense that it does not depend on the state of your Foo class, in which case you could make it static and it will prevent the problem you are experiencing.
  • 您似乎不处理中断您的Runnable。这意味着,即使你叫 future.cancel(真)您的Runnable将继续运行,正如你确定可以为您泄漏的原因。

    You don't seem to handle interruption in your Runnable. That means that even if you call future.cancel(true) your Runnable will continue to run, which as you determined could be a cause for your leak.

    有几种方法可以使一个Runnable中断型。要么你调用(如视频下载()或阻塞的IO方法)方法抛出InterruptedException的,它会抛出一个 InterruptedException的当未来被取消。您可以捕获该异常,并已经清理了哪些需要清理后退出run方法及时恢复被中断的状态:

    There are several ways to make a Runnable "interrupt-friendly". Either you call a method that throws InterruptedException (like Thread.sleep() or a blocking IO method) and it will throw an InterruptedException when the future is cancelled. You can catch that exception and exit the run method promptly after having cleaned up what needs to be cleaned up and restoring the interrupted state:

    public void run() {
        while(true) {
            try {
                someOperationThatCanBeInterrupted();
            } catch (InterruptedException e) {
                cleanup(); //close files, network connections etc.
                Thread.currentThread().interrupt(); //restore interrupted status
            }
        }
    }    
    

    如果您不调用任何这样的方法,标准的成语是:

    If you don't call any such methods, the standard idiom is:

    public void run() {
        while(!Thread.currentThread().isInterrupted()) {
            doYourStuff();
        }
        cleanup();
    }
    

    在这种情况下,你应该尽量确保在当条件定期进行检查。

    In that case, you should try to make sure that the condition in the while is checked regularly.

    通过这些改变,当你调用 future.cancel(真),一个中断信号将被发送到你的执行Runnable的线程将退出在做什么,使您可运行和你的Foo实例资格GC。

    With those changes, when you call future.cancel(true), an interrupt signal will be sent to the thread executing your Runnable which will exit what it is doing, making your Runnable and your Foo instance eligible for GC.

    这篇关于计划的未来可能会导致内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆