How to implement Thread pool in Java without executor framework

Carvia Tech | May 05, 2019 at 07:25 PM | 17 views


Thread pool executor requires a Queue for holding tasks and a collection of Worker Threads that will pick up tasks from the work queue start running them. Let us try to write our own simple Thread Pool Executor implementation. It is a typical Producer Consumer Problem statement.

threadpool executor
Custom ThreadPoolExecutor

Below Java Program provides basic implementation for a working proof of concept for a threadpool executor.

CustomThreadPoolExecutor Basic Implementation
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class CustomThreadPoolExecutor {
    private final BlockingQueue<Runnable> workerQueue;
    private final Thread[] workerThreads;

    public CustomThreadPoolExecutor(int numThreads) {
        workerQueue = new LinkedBlockingQueue<>();
        workerThreads = new Thread[numThreads];
        int i = 0;
        for (Thread t : workerThreads) {
            t = new Worker("Custom Pool Thread " + ++i);
            t.start();
        }
    }

    public void addTask(Runnable r) {
        try {
            workerQueue.put(r);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    class Worker extends Thread {
        public Worker(String name) {
            super(name);
        }

        public void run() {
            while (true) {
                try {
                    workerQueue.take().run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        CustomThreadPoolExecutor threadPoolExecutor = new CustomThreadPoolExecutor(10);
        threadPoolExecutor.addTask(() -> System.out.println("First print task"));
        threadPoolExecutor.addTask(() -> System.out.println("Second print task"));
    }

}

The above program will create pool of 10 worker threads and initialize them all.

Explanation

We are using two classes from standard java library in this implementation:

LinkedBlockingQueue

An optionally-bounded blocking queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). It is thread-safe in nature and acts as a temporary storage of runnable tasks that are due for execution.

Thread

All the threads get initilized and started at the creation of ThreadPoolExecutor. All threads listen on the shared workqueue for incoming tasks in never ending loop.

What we missed

An production grade implementation would have lot more sophistication than the basic implementation provided here, for example:

  1. Capability to tune number of items that can fit into queue.

  2. Capability to configure idle and max worker threads, incase of no work items, number of active threads will reduce to idle threads.

  3. Lazy initialization

  4. Proper exception handling is not implemented in this article

Production usage advise

Always use Executor Framework provided in java.util.concurrent package for executing tasks in your production code. It is simple to use, provides interface-based task execution facility and time tested.

ExecutorService example usage
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(runnable);
exec.shutdown();

Why do we need ThreadPool executor?

There are many reasons one would like to use threadpool executor:

  1. Creating and destroying threads is a IO extensive operation, which has impact on performance and memory consumption of an application. So its ideal to create threads once and reuse them later on.

  2. We do not want to run out of threads when heavy load arrives on an application. Threadpool holds tasks in a queue, so if lot of tasks arrives in a very short amount of time, queue will hold the tasks until a worker thread becomes available for the processing. This approach prevents resource exhaustion in production environment.

  3. If due to some reasons, thread gets killed, ThreadPoolExecutor will recreate the thread and put it back to the pool.


Top articles in this category:
  1. What is Deadlock in Java? How to troubleshoot and how to avoid deadlock
  2. How will you implement your custom threadsafe Semaphore in Java
  3. What is ThreadLocal in Java, where will you use this class
  4. Difference between Implementing Runnable and Extending Thread
  5. What is difference between sleep() and wait() method in Java?
  6. How will you implement a Blocking Queue in Java
  7. What is Immutable Class. Why would you choose it? How would you make a class immutable?


Find more on this topic:
Core Java image
Core Java

Core Java - OOP Concepts, Garbage Collection, Multi-threading, Collections Framework, Java 8 Features, Lambda Functions, Streams.

Last updated 1 month ago


Recommended books for interview preparation:
You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Spring Microservices Interviews for Java Developers
You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Java Interviews v3.5 by Munish Chandel

This website uses cookies to ensure you get the best experience on our website. more info