将代码从使用定时器移植到scheduledexecutorservice [英] Porting code from using timers to scheduledexecutorservice

查看:144
本文介绍了将代码从使用定时器移植到scheduledexecutorservice的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用java 移植代码定时器使用 scheduledexecutorservice

I am trying to port code from using java timers to using 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类,例如

Should I just replace Timer instances in class A and class B with ScheduledExecutorService and make the ATimerTask and BTimerTask class to a Runnable class , for e.g

class B {

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

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

}

这是正确。

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

One of the primary motivation of porting is since runtime exceptions thrown in TimerTask kill that one thread and it cannot be scheduled further. I want to avoid the case so that ieven if I have runtime exception the thread should keep on executing and not halt.

推荐答案

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

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

If your class B will be kept around and each instance will eventually be closed or shut down or released, I would do it like this:

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();
  }
}

如果不对每个人进行这种清理例如,然后我会这样做:

If you will not do this kind of cleanup on each instance, then I would instead do this:

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上,我希望它也可以在其他操作系统上发生。

Each ExecutorService you allocate in your code allocates a single Thread. If you make many instances of your class B then each instance will be allocated a Thread. If these don't get garbage collected quickly, then you can end up with many thousands of threads allocated (but not used, just allocated) and you can crash your whole server, starving every process on the machine, not just your own JVM. I've seen it happen on Windows and I expect it can happen on other OS's as well.

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

A static Cached thread pool is very often a safe solution when you don't intend to use lifecycle methods on the individual object instances, as you'll only keep as many threads as are actually running and not one for each instance you create that is not yet garbage collected.

这篇关于将代码从使用定时器移植到scheduledexecutorservice的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆