In my Java 23 project, IntelliJ IDEA soft-complained that I was calling Executors.newScheduledThreadPool(1)
“without a 'try'-with-resources statement”. To fix this, I accepted IntelliJ's suggestion to surround it with such a try-with-resources block:
@Test
public void testScheduledExecutorServiceTryWithResources() throws InterruptedException {
Logger LOG = LogManager.getLogger();
try (ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1)) {
executorService.scheduleWithFixedDelay(() -> LOG.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
} catch(Exception e) {
LOG.error("testScheduledExecutorService(): Error occurred: {}", e.getMessage(), e);
}
Thread.sleep(5000);
LOG.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
However, this does not work. Here's the console output:
Finishing at 2025-03-03T19:38:08.549627875
Using the ScheduledExecutorService without a try-with-resources block works fine, however:
@Test
public void testScheduledExecutorServiceBare() throws InterruptedException {
Logger LOG = LogManager.getLogger();
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
executorService.scheduleWithFixedDelay(() -> LOG.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
Thread.sleep(5000);
LOG.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
Here's the console output:
Doing something …
Doing something …
Doing something …
Doing something …
Doing something …
Doing something …
Finishing at 2025-03-03T19:30:45.165711955
Why doesn't the try-with-resources block work?
In my Java 23 project, IntelliJ IDEA soft-complained that I was calling Executors.newScheduledThreadPool(1)
“without a 'try'-with-resources statement”. To fix this, I accepted IntelliJ's suggestion to surround it with such a try-with-resources block:
@Test
public void testScheduledExecutorServiceTryWithResources() throws InterruptedException {
Logger LOG = LogManager.getLogger();
try (ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1)) {
executorService.scheduleWithFixedDelay(() -> LOG.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
} catch(Exception e) {
LOG.error("testScheduledExecutorService(): Error occurred: {}", e.getMessage(), e);
}
Thread.sleep(5000);
LOG.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
However, this does not work. Here's the console output:
Finishing at 2025-03-03T19:38:08.549627875
Using the ScheduledExecutorService without a try-with-resources block works fine, however:
@Test
public void testScheduledExecutorServiceBare() throws InterruptedException {
Logger LOG = LogManager.getLogger();
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
executorService.scheduleWithFixedDelay(() -> LOG.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
Thread.sleep(5000);
LOG.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
Here's the console output:
Doing something …
Doing something …
Doing something …
Doing something …
Doing something …
Doing something …
Finishing at 2025-03-03T19:30:45.165711955
Why doesn't the try-with-resources block work?
You are immediately closing the ScheduledExecutorService
when you are using it like you are. The service is close()
ed as soon as you exit the try
block, and since you are not waiting inside you see nothing.
If you want the same output, then you need to wait inside the try
block.
@Test
public void testScheduledExecutorServiceTryWithResources() throws InterruptedException {
Logger LOG = LogManager.getLogger();
try (ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1)) {
executorService.scheduleWithFixedDelay(() -> LOG.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
Thread.sleep(5000);
} catch(Exception e) {
LOG.error("testScheduledExecutorService(): Error occurred: {}", e.getMessage(), e);
}
LOG.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
In my Java 23 project, IntelliJ IDEA soft-complained that I was calling
Executors.newScheduledThreadPool(1)
“without a 'try'-with-resources statement”.
No doubt that diagnostic is based on a general rule that AutoCloseable
objects such as ExecutorService
s should usually be used in a try-with-resources statement. Wrapping new instances that way ensures that they are in fact closed when no longer needed. IntelliJ surely is not expressing a rule specifically about ScheduledExecutorService
.
Why doesn't the try-with-resources block work?
In some cases, it does make sense to wrap a new ExecutorService
in a try-with-resources statement. That expresses the idea of creating the ES for the express, limited purpose of running the tasks assigned to it in the try
clause, waiting for them to complete, and afterward shutting down the ES.
But a ScheduledExecutorService
is a bit different, in that its distinguishing feature is an ability to schedule tasks to be started later. When an SES is closed, all scheduled but unstarted tasks are effectively canceled. They will never be started on account of the SES closure. In your example, control falls out of the try-with-resources statement immediately after your task(s) are scheduled, before any are started, so none ever run. This is try-with-resources working exactly as it should do.
IntelliJ's diagnostic may be overaggressive, but before you say so, consider that your second example has a flaw: it fails to close / shutdown the SES when it has finished with it. This is exactly the problem that a try-with-resources is intended to solve. Just because ExecutorService
s are AutoCloseable
does not mean that they should always be used in conjunction with try-with-resources, but try-with-resources nevertheless looks like a good fit in your particular case. To make it work as you seem to intend, you should move the Thread.sleep()
into the try
clause, preventing the SES from being closed prematurely, but nevertheless ensuring that it is closed when you're ready for that:
@Test
public void testScheduledExecutorServiceTryWithResources() throws InterruptedException {
Logger log = LogManager.getLogger();
try (ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1)) {
executorService.scheduleWithFixedDelay(() -> log.info("Doing something …"), 0, 1, TimeUnit.SECONDS);
Thread.sleep(5000);
} catch(Exception e) {
log.error("testScheduledExecutorService(): Error occurred: {}", e.getMessage(), e);
}
log.info("Finishing at {}", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}