AbstractScheduledService适配性及终止runOneIteration的技术咨询
Hey there! Great question—let's break this down clearly:
Absolutely! This Guava service is designed exactly for periodic tasks like your server status check, where you need to run iterations on a schedule and stop once a condition is met. The RejectedExecutionException you're hitting is just a timing/implementation issue with how you're triggering the shutdown, not a sign the library isn't suited.
Why the exception happens
When you call stopAsync() directly inside runOneIteration(), you're asking the service's executor to submit a new shutdown task. But if your executor is using a single thread (the default setup), that thread is already busy running your current runOneIteration() call. Since there's no free thread to handle the shutdown task, the executor's default rejection policy (AbortPolicy) kicks in and throws the exception.
The fix: Use triggerShutdown() instead
AbstractScheduledService has a protected method called triggerShutdown() that's built for exactly this scenario. It doesn't try to submit a new task to the executor—instead, it marks the service as shutting down:
- Your current
runOneIteration()will finish executing normally (we'll cover how to abort mid-execution if needed below) - The scheduler won't schedule any future iterations
- The service will automatically run your
shutDown()method once everything wraps up
Updated code example
@Override protected void startUp () { LOGGER.log(Level.INFO, () -> "Start-Up of service"); } @Override protected void shutDown () { LOGGER.log(Level.INFO, () -> "Shut-Down of service"); } @Override protected void runOneIteration () { boolean result = this.checkIfServerIsOnline(); if (result) { // Trigger graceful shutdown without submitting a new task triggerShutdown(); LOGGER.log(Level.INFO, () -> "Server is online! Shutting down status check service."); } else { LOGGER.log(Level.INFO, () -> "Server not online yet—will check again in 10 seconds."); } } @Override protected Scheduler scheduler () { return AbstractScheduledService.Scheduler.newFixedRateSchedule(0, 10, TimeUnit.SECONDS); }
If you need to abort checkIfServerIsOnline() mid-execution
If your status check is a long-running operation (e.g., looping until a response comes back) and you want to stop it immediately once the shutdown is triggered, add interrupt checks to your method:
private boolean checkIfServerIsOnline() { while (true) { // Check if the thread has been interrupted (triggered when the service shuts down) if (Thread.currentThread().isInterrupted()) { LOGGER.log(Level.INFO, () -> "Status check interrupted—exiting early."); return false; } // Run your actual server check logic here boolean isServerOnline = performServerHealthCheck(); if (isServerOnline) { return true; } // Optional: Short sleep to avoid hammering the server try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { // Restore the interrupted status so upstream code can handle it Thread.currentThread().interrupt(); return false; } } }
When you call triggerShutdown(), the service will interrupt the thread running runOneIteration(), which your check method will detect and exit promptly.
内容的提问来源于stack exchange,提问作者Hammelkeule

