将代码从使用计时器移植到预定执行器服务

2023-12-08

我正在尝试使用 java 移植代码timers使用预定执行服务

我有以下用例

class A {

    public boolean execute() {
         try {
              Timer t = new Timer();
              t.schedule (new ATimerTask(), period, delay);
         } catch (Exception e) {
              return false;
         }
    }

}


class B {

    public boolean execute() {
         try {
              Timer t = new Timer();
              t.schedule (new BTimerTask(), period, delay);
         } catch (Exception e) {
              return false;
         }
    }

}

我是否应该用 ScheduledExecutorService 替换 A 类和 B 类中的 Timer 实例,并将 ATimerTask 和 BTimerTask 类设置为 Runnable 类,例如

class B {

    public boolean execute() {
         try {
              final ScheduledExecutorService scheduler = 
   Executors.newScheduledThreadPool(1);

              scheduler.scheduleWithFixedDelay (new BRunnnableTask(), period, delay);
         } catch (Exception e) {
              return false;
         }
    }

}

它是否正确。

编辑:移植的主要动机之一是因为 TimerTask 中引发的运行时异常会杀死该线程并且无法进一步调度它。我想避免这种情况,这样即使我有运行时异常,线程也应该继续执行而不是停止。


注意:你这样做的方式会泄漏线程!

如果你的班级B将被保留在周围并且每个实例最终将被关闭或关闭或释放,我会这样做:

class B {
  final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

  public boolean execute() {
    try {
      scheduler.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
      return true;
    } catch (Exception e) {
      return false;
    }
  }

  public void close() {
    scheduler.shutdownNow();
  }
}

如果您不会对每个实例进行这种清理,那么我会这样做:

class B {
  static final ScheduledExecutorService SCHEDULER = Executors.newCachedThreadPool();

  public boolean execute() {
    try {
      SCHEDULER.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
      return true;
    } catch (Exception e) {
      return false;
    }
  }
}

Each ExecutorService您在代码中分配分配一个Thread。如果你为你的类创建了很多实例B那么每个实例都会被分配一个Thread。如果这些不能快速收集垃圾,那么您最终可能会分配数千个线程(但没有使用,只是分配),并且您可能会崩溃整个服务器,使机器上的每个进程都处于饥饿状态,而不仅仅是您自己的 JVM。我已经在 Windows 上看到过这种情况,并且我希望它也可以在其他操作系统上发生。

当您不打算在单个对象实例上使用生命周期方法时,静态缓存线程池通常是一个安全的解决方案,因为您只会保留实际数量的线程running而不是针对您创建的尚未进行垃圾收集的每个实例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将代码从使用计时器移植到预定执行器服务 的相关文章

随机推荐