AppDividend
Latest Code Tutorials

Thread Pools In Java: The Complete Guide

It is an exciting topic, Java-related to multithreading, to perform multiple tasks simultaneously. For example, database and web servers like Server Programs execute requests from various clients every day and the approach through which we can build new threads whenever a request arrives.

But things have a drawback, and its disadvantage is that at every request, our server spends too much time and resources also used, and as there are too many threads that are actively running, this will directly result in memory being out of reach. So to overcome this problem, we have to limit the number of threads actively running.

Thread Pools In Java

Thread pools in Java reuse previously created threads to execute current tasks and offer a solution to the problem of thread cycle overhead and resource thrashing.

Figure

Thread Pools In Java Example

Now the question in your mind is what thread pools are?

Thread pools are the ones that use the previous threads to perform current tasks. Through this, we can solve our problem of resource thrashing and memory wasting.

It also saves the time of thread creation, and hence in this way, the response is very nice. 

Threads are mapped to system-level- threads in Java that directly refer to operating system resources.

Executors, Executor and executor service

Java provides an executor framework centered around the Executor interface. Its sub-interface is executor services, and the class names thread pool executor, implementing both the interfaces.

With the help of the executor, we can handle the running object and send them to the executor to execute these things.

They don’t focus on the thread mechanics, but the main focus is on the task performance by the threads. The threads that will run are running sequentially, not randomly.

ThreadPoolExecutor

Since Java 5, a Java concurrency API provides the mechanism Executor framework. This is around the Executor interface; it’s a sub-interface ExecutorService and a ThreadPoolExecutor class that implements both interfaces.

ThreadPoolExecutor separates a task creation and its execution. With the ThreadPoolExecutor, you only have to implement the Runnable objects and send them to an executor. After that, it is responsible for their execution, instantiation, and running with the necessary threads.

It goes beyond that and improves performance using the pool of threads. When you send the task to the executor, it tries to use the pooled thread to execute the task to avoid continuous spawning of threads.

Methods of Executor thread Pool

#newFixedThreadPool(int)

A fixed-size thread pool has been generated.

#newCachedThreadPool()

Create a thread pool that creates a new thread.

#newSingleThreadExecutor()

When available. Create a single thread.

If the threads are not free in a fixed thread pool and the tasks are pending, they stand in a queue and wait for their turn.

Risks generated in ThreadPool

  1. Deadlock: It occurs in multithreading, and the thread pool introduces another case of deadlock; one case is the threads waiting in the queue due to the unavailability of threads.
  2. Thread Leakage: Thread Leakage occurs when the threads are removed from the pool so that the task can be performed, but in that procedure, if the thread does not return to the pool, this will cause thread leakage.
  3. The thrashing of resources: As we know, if there are more demands in comparison to the possible things, then there is a starvation problem same occurs with the thread; if there are more threads in comparison to the actual optimized level, then there is the problem of starvation.

Now you are thinking about what will be the size of the thread pool

The answer is that it depends on your processor and the nature of the tasks you are giving to your processor.

For the N-type processor system, we can generally take maximum N or N+1 thread pool efficiency. It is a great application that we can use to handle our server.

See the following programming example.

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

class Thread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
    Runnable task = () -> {
      System.out.println("Executing Task At " + System.nanoTime());
    };

    System.out.println("Submitting task at " + System.nanoTime() + " to be executed after 10 seconds.");
    scheduledExecutorService.schedule(task, 10, TimeUnit.SECONDS);

    scheduledExecutorService.shutdown();
  }
}

See the output.

Java Thread Pools Tutorial

Custom thread pool implementation in Java

Java has a very robust thread pool functionality through the Executor framework. And you should not be creating your custom thread pool without an executor. Therefore, I will vehemently discourage any such attempt.

Also, note that incorrect pooling or queue handling can result in deadlocks or resource thrashing. You can certainly avoid these problems with the Executor framework, which is well tested by the Java community.

That’s it for this tutorial.

Recommended Posts

Deadlock in Java

ConcurrentHashMap in Java

Java instanceof Operator

Java Operators

Immutable Class In Java

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.