【问题标题】:My ScheduledThreadPoolExecutor is not shutting down我的 ScheduledThreadPoolExecutor 没有关闭
【发布时间】:2016-01-13 14:27:00
【问题描述】:

我有一个带有 ScheduledThreadPoolExecutor 的 Android 库。它每两秒执行一次任务以检查条件,并在应用程序调用库的 enable() 函数时启动。当应用程序调用 disable() 函数时,该函数会取消 ScheduledFuture 任务并在执行程序上调用 shutdownNow()。问题是它没有停止。在应用程序的日志中,我可以看到 disable() 被调用并查看 Exec Shutdown 到达的位置,但我仍然看到 Exec Runnable 消息在后台运行。事实上,它一直在运行,直到我杀死该应用程序。任何想法为什么任务没有停止?相关代码如下:

private ScheduledThreadPoolExecutor exec;
private ScheduledFuture<?> sf;


private void enable(){
            exec = new ScheduledThreadPoolExecutor(1);
            long period = 2000; 
            exec.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
            exec.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
            sf = exec.scheduleAtFixedRate(new SwitchCheck(), 0, period, TimeUnit.MILLISECONDS);
}


private void disable(){  
        if(exec != null) {
            try {
                Log.d(LOG_TAG,"Exec Shutdown");
                sf.cancel(true);
                exec.shutdownNow();
                exec = null;
            } catch (Exception e){
                e.printStackTrace();
            }
        }
}

class SwitchCheck implements Runnable {

    @Override
    public void run() {
        Log.e(LOG_TAG, "***Exec Runnable***");

    }
}

这里是相关的logcat。调用 updateVisibility 的地方就是我离开活动的地方。

01-13 10:28:41.941 2584-2584/com.genericappname I/Core: onEnable in ENABLING
01-13 10:28:41.941 2584-2584/com.genericappname D/Core: SDK state change from ENABLING to ENABLED
01-13 10:28:41.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:41.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:42.241 2584-2584/com.genericappname D/Core: enable ENABLED
01-13 10:28:42.251 2584-3694/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:45.491 2584-2584/com.genericappname V/ActivityThread: updateVisibility : ActivityRecord{38270d8e token=android.os.BinderProxy@177d3607 {com.genericappname/com.genericappname.Demo}} show : true
01-13 10:28:45.501 2584-2584/com.genericappname D/SRIB_DCS: log_dcs ThreadedRenderer::initialize entered! 
01-13 10:28:45.501 2584-2669/com.genericappname D/mali_winsys: new_window_surface returns 0x3000,  [1440x2560]-format:1
01-13 10:28:45.561 2584-2584/com.genericappname D/ViewRootImpl: changeCanvasOpacity: opaque=false
01-13 10:28:45.891 2584-2584/com.genericappname D/DEMO: onPause
01-13 10:28:45.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:45.951 2584-2584/com.genericappname D/Core: disable
01-13 10:28:45.951 2584-2584/com.genericappname D/Core: SDK state change from ENABLED to DISABLING
01-13 10:28:45.951 2584-2584/com.genericappname I/Core: onDisable
01-13 10:28:45.951 2584-2584/com.genericappname D/Core: SDK state change from DISABLING to INITIALIZED
01-13 10:28:45.951 2584-2584/com.genericappname D/Core: Exec Shutdown
01-13 10:28:46.001 2584-2584/com.genericappname I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@177d3607 time:87045589
01-13 10:28:46.011 2584-2584/com.genericappname D/DEMO: onStop
01-13 10:28:46.011 2584-2584/com.genericappname D/DEMO: onDestroy
01-13 10:28:47.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:47.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:49.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:49.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:51.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:51.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:53.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:53.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:55.941 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:55.941 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23
01-13 10:28:57.951 2584-3650/com.genericappname E/Core: ***Exec Runnable***
01-13 10:28:57.951 2584-3650/com.genericappname D/Core: ThisId: 0 thisExpectedId: 23

【问题讨论】:

  • 所以它会继续每 2 秒产生一次线程?
  • 你能添加一些 logcat 输出吗?乍一看,我觉得还可以。
  • 您是否有机会看到以前未完成的线程调用的日志?即使您调用禁用,队列中也可能有以前安排的作业。
  • @BharathMg 这些将不会按照文档执行:developer.android.com/reference/java/util/concurrent/…
  • @Fildor 那么他有可能在两个不同的对象上调用 enable() 触发独立的 ScheduledThreadPoolExecutors ?

标签: java android threadpoolexecutor


【解决方案1】:

在调用 disable 之前第二次调用该方法会发生什么:

private void enable(){
            exec = new ScheduledThreadPoolExecutor(1); // Creates a NEW scheduler and takes the place of the old one. But the old one still exists and does its duty!
            long period = 2000; 
            exec.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
            exec.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
            sf = exec.scheduleAtFixedRate(new SwitchCheck(), 0, period, TimeUnit.MILLISECONDS);
}

exec 将指向一个新的 Executor,第一个 Executor 将继续执行任务。

你需要检查是否

  1. 您已经有一个尚未关闭的 Executor。
  2. 您已经有了任务计划。如果是这样,enable 是无操作的。

【讨论】:

  • 在完整函数中,如果enable被调用两次,逻辑检查将跳过新Executor的设置。我只是没有在这个例子中包含这个逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 2023-03-06
  • 2023-03-23
  • 2016-03-26
  • 2013-04-09
  • 1970-01-01
  • 2014-07-14
相关资源
最近更新 更多