【发布时间】:2021-12-28 08:11:02
【问题描述】:
我仍在努力了解如何使用 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...
但是,我这只是因为我在等待latchTwo 之前等待latchOne,因为第一个任务花费的时间更少。如果我切换这个顺序,即
latchTwo.await();
scheduledFutureTwo.cancel(false);
latchOne.await();
scheduledFutureOne.cancel(false);
任务一将被进一步执行,即使锁存器已达到零,因为它仅在任务二之后被取消。有没有办法在锁存器为零时立即执行某些操作(在这种情况下为 scheduledFutureOne.cancel(false))并同时对多个锁存器执行此操作?
我还尝试按照this answer 中描述的设置再次运行良好,但我不知道在哪里/如何关闭 ExecutorService。设置类似,增加一个原子整数,直到达到所需的调用次数,然后我们取消未来。不过,这仍然不会关闭 ExecutorService。
TLDR 我想用一个 ExecutorService 安排多个任务,每个任务都有固定数量的调用。 ExecutorService 处理任务的顺序应该允许是随机的。一旦不再安排任何任务,ExecutorService 就应该关闭。
谢谢你们的任何想法:)
【问题讨论】:
-
在
run()方法内的一个简单的for循环中安排一个完成五或十个任务的大任务是否是一种选择?是否可以立即将同一任务安排五次或十次? -
有什么特别的原因要关闭它吗?
Executors.newCachedThreadPool()不满足您的要求的任何特殊原因? -
您好,感谢您的回答。 @Progman 我不太喜欢第一个选项,因为这只是一个示例,它更像是 100000 个任务,然后 for 循环似乎有些笨拙。我看不出一次安排所有任务有什么问题,但还没有真正看到好处吗?
-
@Shark 老实说,我只是想关闭它,因为这似乎是正确的做法 - 如果我不再使用资源,请清理它。而且它会被多次调用,所以我不想在某个时候有很多空闲的 executorServices。我刚刚阅读了 newCachedThreadPool ,它看起来很不错,尽管有些人仍然说在这里也应该调用shutdown。我会再读一些,谢谢你的建议:)
-
嗯....我不知道。让一个 ExecutorService 在应用程序启动时初始化并在应用程序停止时关闭(对我来说)似乎比初始化 ExecutorService、运行一批任务并关闭它——每次你想要执行一些任务。
标签: java executorservice scheduledexecutorservice