FixedSizeThreadPoolExecutor in Java Executor Framework
In a fixed thread pool, the number of threads in the pool depends on the type of task. For CPUs-intensive tasks like encryption, implementing hash algorithms, the number of threads depends on the number of cores. Thus, every thread runs on its core and once it is done executing the task it picks up the next task from the queue. Also, there could be a possibility that multiple applications are running, so not all cores might be accessible.
For an IO-intensive task that involves too many DB calls or HTTP calls, if there are fewer threads, then there might be too many threads waiting for these IO calls to complete. Thus, CPUs time is wasted and so it makes sense to have more threads. In this way, few threads get to do some processing/calculations utilizing the CPU time and few threads might be waiting for DB/HTTP calls to complete.
Approach 1: Standard approach
In java, when you want to run your task in an asynchronous manner, you spawn threads and make the threads execute the task. For this, we have a class that implements the Runnable interface. Then we pass an instance of Runnable to the thread which then executes the task.
Example
Java
import java.io.*;
import java.util.*;
public class GFG {
public static void main(String[] args)
{
for ( int i = 0 ; i < 5 ; i++) {
Thread thread = new Thread(() -> {
System.out.println(
"Printing document by thread : "
+ Thread.currentThread().getName());
try {
Thread.sleep(1000L);
}
catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
}
}
|
Note: The order of executing the task changes with each run.
Output Explanation:
Here in the main thread spawns 5 threads, each of which given an instance of Runnable implementation. When we say thread.start(), the runnable implementation’s run method gets invoked and the task is executed.
Approach 2:
Till now, we have discussed the above approach and have gone through the output fluctuations with each run. There was a necessity for laying down another approach because as a developer, we need to handle the creation and management of threads which becomes tedious when there are many threads in an application. For this purpose, we have the ExecutorService framework which helps in the management of threads. As a developer, we choose the type of thread pool that the executor service must create and delegate the responsibility of thread management to the executor service. In Fixed Size thread pool executor, we create a fixed number of threads in the pool and submit tasks to the executor service. The submitted tasks get stored in the blocking queue, Each thread picks up a task from the blocking queue and executes it, and moves on to the next tasks. The blocking queue is implemented in such a way that it can handle concurrent operations especially when multiple threads try to pick up the same task from the queue.
Example:
Java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class GFG {
public static void main(String[] args)
{
ExecutorService service
= Executors.newFixedThreadPool( 3 );
for ( int i = 0 ; i < 5 ; i++) {
service.execute(() -> {
System.out.println(
"Printing document by thread : "
+ Thread.currentThread().getName());
try {
Thread.sleep(1000L);
}
catch (InterruptedException e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
}
|
Output:
Output Explanation:
Here we created a thread pool with 3 threads where we submitted 5 tasks to the executor service. This executor service takes care of executing the submitted task by the threads from the thread pool. The executor service takes care of creating the thread pool. So here thread name is pool-X-thread-Y.
Last Updated :
05 Jul, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...