让我们假设我计划在我的整个应用程序中使用一个executorservice,我正在发送新的runnable或callable来执行/提交,并且我在执行此操作后立即关闭。我只想把我的“任务”扔给executorservice并让他处理它们并执行它们给它的资源(他有多少线程可用,如果需要可以创建多少线程,然后相应地排队这些任务)。
根据您在Android应用程序中使用ExecutorService的经验,并考虑到应用程序状态的变化,如果我不想通过这样做不断关闭并重新创建执行程序服务:
executor = Executors.newCachedThreadPool();
executor.submit(some Runnable);
executor.shutdown();
,您将在什么时间和地点推荐关闭服务,然后恢复它以便我可以防止一些泄漏或一些不可预见的后果?
我大部分时间都在努力:
1)在Backstack中的最后一个活动上通过后退按钮关闭应用程序(应用程序使用许多活动) 2)申请在后台进行(在任何这些活动上) 3)应用程序返回到前台(在任何这些活动上)
答案 0 :(得分:10)
你可以做一个解决方法。将执行程序创建为守护程序。然后它会在您的应用程序退出时自动结束。您无需明确调用shutdown
。
ExecutorService es = Executors.newSingleThreadExecutor( new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
答案 1 :(得分:4)
我有一个ExecutorService的单例实例,它通过Dagger的对象图限定为Android应用程序实例。 因此,实例与Application对象本身一样长。由于Android的Application类不提供onDestroy()回调,因此在ExecutorService上调用shutdown()时永远不知道。
由于我害怕内存泄漏,我也在调查ThreadPoolExecutor并使用它来查找。这是我发现的:Executors.newCachedThreadPool()使用以下参数创建一个ThreadPoolExecutor:
ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())
这是一个0的corePoolSize,这意味着最少0个工作线程保持活动状态,因此没有。当TPE(a.k.a ExecutorService)执行任务时,它会创建一个工作线程并将其添加到池中。现在,当60秒超时期间没有新任务进入时,(仍保持活动状态)工作线程终止并从池中移除(缓存)。
对我而言,这意味着即使从未在ExecutorService上调用shutdown()也不会发生内存泄漏,因为所有工作线程都存在,超时并且在没有新任务时将从池中删除在超时期间进来。 我想那样,就不会有任何对工作线程的引用,因此GC可以清理TPE实例。
如果我错了,请随意纠正我。
答案 2 :(得分:0)
尽管这个问题已经发布多年了,但最近 Android API 30 已弃用 AsyncTask,有人可能会卡在这里。为了回答这个问题,没有必要关闭单例 ExecutorService 除非它有任何空闲线程。根据{{3}}:
<块引用>不再在程序中引用并且没有剩余的池
线程将自动 shutdown
。如果您想确保
即使用户忘记调用,未引用的池也会被回收
shutdown()
,那么你最终必须安排那些未使用的线程
死,通过设置适当的保持活动时间,使用下限
零核心线程...
对于这种情况,Executors.newCachedThreadPool()
是一个很好的工厂方法。当您的应用进程终止时,它会自动关闭。
MyApplication.java:
public class MyApplication extends Application {
private static ExecutorService executorService = Executors.newCachedThreadPool();
...
public static Executor getExecutor() {
return executorService;
}
}
只需在代码中的任何位置使用 MyApplication.getExecutor()
。