ScheduledExecutorService is an interface that extends ExecutorService and provides methods for scheduling tasks to run after a delay or periodically.newSingleThreadScheduledExecutor() method creates an executor that uses a single worker thread to execute scheduled tasks sequentially.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
Note: The Apache Commons Lang3 dependency is included for the BasicThreadFactory class,
which provides convenient thread naming and daemon thread configuration.
While Java's built-in Executors.newSingleThreadExecutor works without additional dependencies,
using a custom ThreadFactory allows better thread management and debugging.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
public class MainClass {
public static void main(String[] args) throws InterruptedException {
// The time to wait before the first execution
final long INITIAL_DELAY = 500l;
// The time to wait between the completion of one execution and the start of the next
final long DELAY = 1000l;
final String namingPattern = "_newSingleThreadScheduledExecutor";
final BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder();
// Configures thread properties
// namingPattern sets custom thread names
// daemon(true) makes threads daemon threads (JVM can exit even if these threads are running)
final BasicThreadFactory basicThreadFactory = builder.namingPattern(namingPattern).daemon(true).build();
final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(basicThreadFactory);
final Runnable runnable = () -> System.out.println(Thread.currentThread().getName() + ": Hello!");
// Schedules repeated execution with a fixed delay between the end of one execution and the start of the next
scheduledExecutorService.scheduleWithFixedDelay(runnable, INITIAL_DELAY, DELAY, TimeUnit.MILLISECONDS);
// Blocks until all tasks complete or timeout occurs
scheduledExecutorService.awaitTermination(5000l, TimeUnit.MILLISECONDS);
// Initiates orderly shutdown - no new tasks accepted, but previously submitted tasks continue
scheduledExecutorService.shutdown();
}
}
Output:_newSingleThreadScheduledExecutor: Hello! _newSingleThreadScheduledExecutor: Hello! _newSingleThreadScheduledExecutor: Hello! _newSingleThreadScheduledExecutor: Hello! _newSingleThreadScheduledExecutor: Hello!