当前位置: 首页 > 知识库问答 >
问题:

如何正确关闭计划执行服务

谷梁楷
2023-03-14

我仍在努力理解如何使用ScheduledExecutorService。我想要一个ScheduledExecutorService/ScheduledThreadPoolExecutor,它调度多个任务,并允许它们运行固定的时间。一旦不再调度任务,我就要关闭ScheduledThreadPoolExecutor。我试图通过编写一些测试来理解这是如何工作的。我尝试的第一件事是:

    @Test
    public void testExecutorService() throws Exception {
        ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
        executorService.setRemoveOnCancelPolicy(true);
        CountDownLatch latchOne = new CountDownLatch(5);
        CountDownLatch latchTwo = new CountDownLatch(10);

        ScheduledFuture<?> scheduledFutureOne = executorService.scheduleAtFixedRate(new MyRunnerOne(latchOne), 0, 1, TimeUnit.SECONDS);
        ScheduledFuture<?> scheduledFutureTwo = executorService.scheduleAtFixedRate(new MyRunnerTwo(latchTwo), 0, 2, TimeUnit.SECONDS);
        
        latchOne.await();
        scheduledFutureOne.cancel(false);
        latchTwo.await();
        scheduledFutureTwo.cancel(false);
        
        System.out.println("Shutting down service...");
        executorService.shutdown();
        Thread.sleep(100);
        assertTrue(executorService.isTerminated());
    }

    class MyRunnerOne implements Runnable
    {
        CountDownLatch latch;

        MyRunnerOne(CountDownLatch latch)
        {
            this.latch = latch;
        }

        @Override
        public void run()
        {
            System.out.println("Do Task One : " + latch.getCount());
            latch.countDown();
        }
    }


    class MyRunnerTwo implements Runnable
    {
        CountDownLatch latch;

        MyRunnerTwo(CountDownLatch latch)
        {
            this.latch = latch;
        }

        @Override
        public void run()
        {
            System.out.println("Do Task Two: " + latch.getCount());
            latch.countDown();
        }
    }

这工作得很好,我得到了预期的输出:

Do Task One : 5
Do Task Two: 10
Do Task One : 4
Do Task One : 3
Do Task Two: 9
Do Task One : 2
Do Task One : 1
Do Task Two: 8
Do Task Two: 7
Do Task Two: 6
Do Task Two: 5
Do Task Two: 4
Do Task Two: 3
Do Task Two: 2
Do Task Two: 1
Shutting down service...

然而,我认为这只是因为我在等待LatchTo之前等待latchOne,因为第一个任务花费的时间更少。如果我改变这个顺序,也就是。

        latchTwo.await();
        scheduledFutureTwo.cancel(false);
        latchOne.await();
        scheduledFutureOne.cancel(false);

任务一将被进一步执行,即使锁存已经达到零,因为它只在任务二之后被取消。有没有一种方法可以在锁存为零时立即执行某件事情(在这种情况下ne.cancel为false),并且一次执行多个锁存?

我也试图按照这个答案中描述的设置,它再次运行良好,但我不知道在哪里/如何关闭ExecutorService。设置类似,增加一个原子整数,直到达到所需调用的数量,然后我们取消未来。不过,这仍然不会关闭ExecutorService。

TLDR我希望使用单个ExecutorService来安排多个任务,每个任务用于固定数量的调用。应该允许ExecutorService处理任务的顺序是随机的。一旦不再计划任何任务,则应关闭ExecutorService。

谢谢你们的任何想法:)

共有1个答案

乐正涵忍
2023-03-14

如果您在执行器服务中重新安排任务本身,这将更容易做到:

ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
CountDownLatch latchOne = new CountDownLatch(1);
CountDownLatch latchTwo = new CountDownLatch(1);

executorService.submit(new MyRunnerOne(executorService, latchOne, 5));
executorService.submit(new MyRunnerTwo(executorService, latchTwo, 10));

latchTwo.await();
latchOne.await();

System.out.println("Shutting down service...");
executorService.shutdown();
executorService.awaitTermination(100, TimeUnit.SECONDS);
System.out.println("Terminated: " + executorService.isTerminated());

//...

class MyRunnerOne implements Runnable {
    private final ExecutorService service;
    private final CountDownLatch latch;
    private final int count;

    MyRunnerOne(ExecutorService service, CountDownLatch latch, int count) {
        this.service = service;
        this.latch = latch;
        this.count = count;
    }

    @Override
    public void run() {
        System.out.println("Do Task One : " + count);
    
        if (count > 1) {
            service.submit(new MyRunnerOne(service, latch, count - 1));
        } else {
            latch.countDown();
        }
    }
}

完整代码。

 类似资料:
  • 问题内容: 我需要从 网址获得回调后关闭服务器。使用通常的 HTTP API, 关闭服务器当前支持 API功能,但是使用节点表达服务器时 出现错误。而且我不知道如何找到解决此问题的信息。 我应该如何关闭快递服务器? NodeJS配置说明: 实际应用代码: 另外,我发现[‘nodejs expressclose…’,]但是我不确定是否可以将其用于具有以下代码的代码中:。 问题答案: 返回。您应该在该

  • 问题内容: 我有全部传播异常的方法,然后在一个地方处理,但是我意识到了一些事情。 假设我有这样的方法 我的问题是,如果doSometing()方法引发异常,该语句将不会关闭,但我不想在那里处理异常。尝试并捕获只会抛出异常并最终关闭语句的正确方法吗? 问题答案:

  • 问题内容: 在清理一些代码时,FindBugs向我介绍了一些使用Connection,CallableStatement和ResultSet对象的JDBC代码。这是该代码的一个片段: FindBugs指出这些应该在finally块内。我开始重构我的代码来做到这一点,我开始想知道如何在finally块中处理代码。 Connection对象的CallableStatement的创建可能会引发异常,而我

  • 问题内容: 其中哪一个是正确的? 问题答案: 工作正常,并正确关闭标签。最好为视障人士添加属性。

  • 问题内容: 如何正确关闭IPython Notebook? 目前,我只是关闭浏览器选项卡,然后在终端中使用。 不幸的是,滴答也无济于事(它们确实杀死了它们的内核,但没有退出iPython)。 问题答案: 当前没有比终端中的Ctrl + C更好的方法了。 我们正在考虑如何进行显式关机,但是笔记本作为单用户应用程序(用户可以自由停止它)和作为多用户服务器(只能由管理员操作)之间存在一些紧张关系。阻止它

  • 我有一个简单的java,它运行一些任务对象(实现)。 除了尽最大努力尝试停止处理正在执行的任务之外,没有任何保证。例如,典型的实现将通过{@link thread#interrupt}取消,因此任何未能响应中断的任务都可能永远不会终止。 我的问题是,有没有办法确保那些(任务)线程会终止?我想出的最佳解决方案是在程序末尾调用,但这显然是愚蠢的。