简体   繁体   English

无法停止在ScheduledExecutorService.schedule中传递自身的Runnable

[英]can't stop a Runnable that passing itself in ScheduledExecutorService.schedule

I have a poller implemented from Runnable. 我有一个从Runnable实现的轮询器。 The poller passes itself into a ScheduledExecutorService. 轮询器将自身传递给ScheduledExecutorService。 Since I need different delay time depending on the tasks, I use 'schedule' instead of 'scheduleWithFixedDelay', which got a problem... 由于我根据任务需要不同的延迟时间,因此我使用“ schedule”而不是“ scheduleWithFixedDelay”,这带来了问题...

Unfortunately, this poller can't shut down properly... 不幸的是,该轮询器无法正确关闭...

The log shows that: at beginning, 'main' thread schedules a poller; 日志显示:开始时,“主”线程调度一个轮询器; after that, 'poller18' (or whatever thread id) thread schedules the following pollers. 之后,“ poller18”(或任何线程ID)线程将调度以下轮询器。

When destroyed, 'main' thread calls destroy, set the flag to true, and then call poller.shutdown; 销毁后,“ main”线程调用destroy,将标志设置为true,然后调用poller.shutdown;。 but 'poller18' thread never see that flag (it is always false in schedulePoller), so it will keep scheduling next pollers. 但是'poller18'线程永远不会看到该标志(在schedulePoller中始终为false),因此它将继续调度下一个轮询器。

My questions are: 1. isShuttingDown is a private field in the class. 我的问题是:1. isShuttingDown是类中的私有字段。 I thought it would be shared by the threads since it is not ThreadLocal. 我认为它将由线程共享,因为它不是ThreadLocal。 Why isn't it? 为什么不呢 2. in this situation, is there any other way poller18 can be notified that poller is shutting down? 2.在这种情况下,是否可以通过其他任何方式通知poller18轮询器正在关闭?

class Poller implements Runnable {
    private boolean isShuttingDown = false;
    private ScheduledExecutorService poller = null;

    @PostConstruct
    protected synchronized void start() {
      if (enabled && poller == null) {
          poller = Executors.newScheduledThreadPool(1);
          schedulePoller(1);
      }
   }

   protected synchronized void schedulePoller(final long period) {
      if (poller() == null || poller().isShutdown() || this.isShuttingDown) {
          return;
      }
      LOGGER.info("schedule a new poller");
      poller().schedule(this,
              period,
              TimeUnit.MILLISECONDS);
   }

   public void run() {
      ... do work ...
      if (more work)
           schedulePoller(1);
      else
           schedulePoller(10);
   }

   public void destroy() {
      this.isShuttingDown = true;
      poller.shutdown();
      while (!poller.awaitTermination(SHUTDOWN_WAIT_SECONDS, TimeUnit.SECONDS)) {
          LOGGER.info("Waiting for remaining tasks to finish.");
          poller.shutdown();
      }
      LOGGER.info("All remaining tasks have finished.");
   }
}

And in spring config, I set destroy_method to destroy(). 在spring config中,我将destroy_method设置为destroy()。

Many thanks! 非常感谢! Please let me know if any confusions in my description. 如果我的描述有任何混淆之处,请告诉我。

try 尝试

private volatile boolean isShuttingDown = false;

Thread Pooling 线程池

The javadoc isn't very clear regarding the behavior of new schedules if the executor is shutting down. 如果执行程序正在关闭,则javadoc对于新计划的行为不是很清楚。 In my understanding, it should reject new schedules. 以我的理解,它应该拒绝新的时间表。

Anyway, the poller thread doesn't see the value of your flag because it's not synchronized. 无论如何,轮询程序线程不会看到您的标志的值,因为它没有同步。 You need to synchronize all its accesses, or to make it volatile. 您需要同步其所有访问,或使其可变。 Another way is to use an AtomicBoolean, which will encapsulate this for you. 另一种方法是使用AtomicBoolean,它将为您封装它。

When accessing the shared state (isShuttingDown), whether it is read or write access, you need to always hold the same lock in order to have consistent shared state between threads. 当访问共享状态(isShuttingDown)时,无论是读访问还是写访问,您都必须始终持有相同的锁,以便线程之间具有一致的共享状态。 destroy() method is not synchronized and therefore does not hold a the same object lock(the implicit lock on the current/"this" class instance), while it changes the shared state variable. destroy()方法未同步,因此在更改共享状态变量时不会拥有相同的对象锁(当前/“ this”类实例上的隐式锁)。 This is most probably why isShuttingDown is not seen correctly by all threads... 这很可能就是为什么所有线程都无法正确看到isShuttingDown的原因...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何返回传递给 ScheduledExecutorService.schedule 的 Runnable 或 Callable 的返回值 - How to return the return value of the Runnable or Callable passed to ScheduledExecutorService.schedule 为什么ScheduledExecutorService.schedule()启动的线程永远不会终止? - Why does the thread started by ScheduledExecutorService.schedule() never terminate? 无法编译调用自身的runnable吗? - Can't compile runnable that calls itself? 为什么不能从Runnable命令本身关闭ScheduledExecutorService? - Why ScheduledExecutorService cannot be shutted down from the Runnable command itself? 如何取消ScheduledExecutorService / Runnable以便在回压/退出活动时停止加载InterstitialAd - How to cancel ScheduledExecutorService/ Runnable to stop loading the InterstitialAd on backpress/exit the activity 在ScheduledExecutorService中运行的任务本身内停止定期任务 - Stop a periodic task from within the task itself running in a ScheduledExecutorService 使用Runnable和ScheduledExecutorService的内存泄漏 - Memory leak with Runnable and ScheduledExecutorService ScheduledExecutorService 计划未触发 - ScheduledExecutorService schedule not triggering java ScheduledExecutorService可运行的异常处理 - java ScheduledExecutorService runnable exception handling ScheduledExecutorService-忽略已运行的可运行文件 - ScheduledExecutorService - Ignore already running runnable
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM