• Home
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All
  • About
Java | Fixed Thread Pool
  1. Fixed Thread Pool
  2. Example: ExecutorService::execute(Runnable)

  1. Fixed Thread Pool
    The ExecutorService framework provides a higher-level replacement for working with threads directly. It manages thread pools, handles thread lifecycle (creation, scheduling, and cleanup), and provides various execution strategies.

    A fixed thread pool maintains a constant number of threads. When all threads are busy, new tasks wait in a queue until a thread becomes available.

    Here's the minimal dependencies needed in order for the following example to work ("pom.xml" file):
    <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.newFixedThreadPool works without additional dependencies, using a custom BasicThreadFactory allows better thread management and debugging.
  2. Example: ExecutorService::execute(Runnable)
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.IntStream;
    
    import org.apache.commons.lang3.concurrent.BasicThreadFactory;
    
    public class MainClass {
        public static void main(String[] args) throws InterruptedException {
            final String namingPattern = "_newFixedThreadPool";
    
            // A builder pattern for creating custom thread factories
            final BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder();
    
            // Creates a thread factory with custom naming pattern and daemon threads
            // Daemon threads don't prevent JVM shutdown when main program ends
            final BasicThreadFactory basicThreadFactory = builder.namingPattern(namingPattern).daemon(true).build();
    
            // Creates a fixed thread pool with 2 threads using the custom thread factory
            final ExecutorService executorService = Executors.newFixedThreadPool(2, basicThreadFactory);
    
            // Creates an infinite stream starting from 0, incrementing by 1, and limits the stream to 5 elements (0, 1, 2, 3, 4)
            // Executes the lambda for each element
            IntStream.iterate(0, i -> i + 1).limit(5).forEach(t -> executorService.execute(() -> {
                try {
                    // Pauses current thread execution for specified milliseconds
                    // Random sleep between 1-100ms to simulate varying task durations
                    Thread.sleep(new Random().nextInt(100) + 1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                System.out.println(Thread.currentThread().getName() + ": " + t);
            }));
    
            // Blocks until all tasks complete or timeout occurs
            executorService.awaitTermination(1000l, TimeUnit.MILLISECONDS);
    
            // Initiates orderly shutdown where previously submitted tasks are executed but no new tasks will be accepted.
            // Does not wait for tasks to complete.
            executorService.shutdown();
        }
    }
    Output:
    _newFixedThreadPool: 1
    _newFixedThreadPool: 0
    _newFixedThreadPool: 2
    _newFixedThreadPool: 4
    _newFixedThreadPool: 3
    Since only 2 threads are available but 5 tasks are submitted, tasks will be queued and executed as threads become available. The random sleep times cause tasks to complete in unpredictable order, which is why the output numbers may not be sequential (1, 0, 2, 4, 3).
© 2025  mtitek