当前位置:  开发笔记 > 编程语言 > 正文

将代码从使用定时器移植到scheduledexecutorservice

如何解决《将代码从使用定时器移植到scheduledexecutorservice》经验,为你挑选了1个好方法。

我正在尝试将代码从使用java 计时器移植到使用scheduledexecutorservice

我有以下用例

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中抛出的运行时异常会杀死一个线程并且无法进一步调度.我想避免这种情况,以便即使我有运行时异常,线程应该继续执行而不是停止.



1> Eddie..:

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

如果您的班级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;
    }
  }
}

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

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

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有