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

我正在尝试将代码从使用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中抛出的运行时exception会杀死一个线程并且无法进一步调度。 我想避免这种情况,以便即使我有运行时exception,线程应该继续执行而不是停止。

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

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

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

看起来不错。 根据您正在做的事情,您可能希望将执行程序服务作为成员保留,以便您可以再次使用它。 此外,您可以从scheduleXX()方法返回ScheduledFuture。 这很有用,因为您可以在其上调用get()以将定时线程中发生的任何exception提取回控制线程进行处理。

目前没有好的方法来处理Executors框架中的重复任务。

它确实没有考虑到这个用例,并且没有现实的方法来避免吞咽exception。

如果你真的必须用它来重复任务,那么每个调度都应该是这样的:

 scheduler.scheduleWithFixedDelay(new Runnable() { public void run() { try { .. your normal code here... } catch (Throwable t) { // handle exceptions there } } }, period, delay);