切换 ScheduledExecutorService 所以它并不总是 运行

Toggle ScheduledExecutorService so its not always running

我目前正在开发一个 discord 机器人,只是为了搞乱,但过去曾使用 SES 做其他事情,但我总是难以 disable/enable SES,调用 ses.shutdown();不工作,runnable 继续,如果我关闭了我不知道如何重新启动它。

这是我当前的代码...

private final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

protected void startRainbow(Role rle) {
    roleRainbow[] colors = roleRainbow.values();
    HashMap<String, Integer> map = new HashMap<>();
    map.put("loop", 0);

    Runnable r = () -> {

        if(map.get("loop") >= colors.length) {
            map.put("loop", 0);
        }



        rle.getManager().setColor(Color.decode(colors[map.get("loop")].toString())).queue();
        System.out.println("color is: " + colors[map.get("loop")].toString());
        System.out.println("color from role: " + rle.getColor());

        map.put("loop", map.get("loop") + 1);
    };

    ses.scheduleAtFixedRate(r, 1L, 1, TimeUnit.SECONDS);
}

这个问题有两个角度:

  • 正在中断 currently-running 线程。
  • 正常关闭计划的执行程序服务。

第一个问题已经解决 many many times on Stack Overflow。简而言之:您必须向线程发出信号,表明您希望它中断自身。该线程的任务必须编码就是这样一种寻找中断信号的方式。

对于第二种,涉及两个步骤:

  • 您首先告诉计划的执行程序服务您要停止任何进一步执行 future-scheduled 任务。我们通过调用 shutdown 来完成此操作。此调用 不会 中断任何当前存在的任务(见上段)。
    • 或者,您可以调用 shutdownNow。此调用 可能 向 运行 任务发出中断信号,但不能保证。行为是 implementation-defined.
  • 请求服务停止进一步调度后,您可以观察服务是否确实在经过一段合理的时间后停止。我们通过调用 awaitTermination.
  • 来做到这一点
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
ses.scheduleAtFixedRate( task , initialDelay , period , timeUnit ) ;
…
ses.shutdown() ;
boolean terminated = false ;
try { terminated  = ses.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }
if( ! terminated ) { … Houston, we have a problem. … }

shutdown(和shutdownNow)的调用不会阻塞;它不等待任何事情发生,也不等待任务结束。

awaitTermination 的调用确实 阻塞,直到:

  • 计划的执行程序服务完成其最后一个 运行 任务,然后结束。
  • 指定的 time-out 已过。

测试 awaitTermination 调用返回的布尔值。引用 Javadoc:

true if this executor terminated and false if the timeout elapsed before termination

你问过:

if I did shutdown im not sure how to restart it.

一旦关闭,预定的执行程序服务就完成了。要安排任务执行,您必须实例化一个新的计划执行程序服务。

请注意,没有要执行的任务的计划执行程序服务占用非常少的内存或CPU。因此,如果您以后可能需要该服务,则无需关机。

但是,请务必始终 在您的应用程序结束之前关闭您的执行程序服务。否则后备线程池可能会 运行 无限期地继续,就像僵尸 ‍♂️。