Pages

Label

Rabu, 30 Januari 2019

Thread Pool in Java

Hello Guys !!! Hope You all are doing well . Today I am going to discuss Thread pool .
  • Java 1.5 introduced Thread pool in Java in the form of Executor framework.
  • Thread pool in Java is a pool of worker threads, which is ready to perform any task given to them, mostly in the form of implementation of Runnable or Callable interface.
  • Since Java supports multithreading in programming language itself, it allows multiple threads to run concurrently and perform parallel processing of the task. 
What is Thread pool in Java? and Why do we need it ?
  • As I said Thread pool is a pool of already created worker thread ready to do the job.
  • The thread pool is important for any multi-threaded server side Java application
  • As for example Using thread pool to create a web server, which processes client request.
  • If only one thread is used to process client request, In that case one connection per client.
  • In order to support large number of clients, we may decide to use one thread per request paradigm, in which each request is processed by a separate Thread, but this require Thread to be created, when request arrived. Since creation of Thread is time consuming process, it delays request processing.
  • Apart from that there is also limit for "How many thread per JVM", which is obviously a limited number.
  • Thread pool solves this problem for us, It creates Thread and manage them.
  • Instead of creating Thread and discarding them once task is done, thread-pool reuses threads in form of worker thread.
  • Since Thread are usually created and pooled when application starts, your server can immediately start request processing, which can further improve server’s response time.
In short, we need thread pools to better mange threads and decoupling task submission from execution.
Java Thread Pool - Executor Framework in Java 5
Java 5 introduced several useful features:-
  • Enum,
  • Generics,
  • Variable arguments and
  • several concurrency collections and utilities like :-
  • ConcurrentHashMap and BlockingQueue etc,
It also introduced a full feature built-in Thread Pool framework commonly known as Executor framework.
The core of thread pool framework is Executor interface which defines an abstraction of task execution with method execute(Runnable task) and ExecutorService which extends Executor to add various life-cycle and thread pool management facilities like shutting down thread pool.
Executor framework also provides a static utility class called Executors ( similar to Collections) which provides several static factory method to create various type of Thread Pool implementation in Java e.g.
  • fixed size thread pool,
  • cached thread pool
  • scheduled thread pool
Runnable and Callable interface are used to represent task executed by worker thread managed in these Thread pools
Here are four factory method present in Executors class
newFixedThreadPool:
This method returns thread pool executor whose maximum size(let’s say n threads) is fixed. If all n threads are busy performing the task and additional tasks are submitted, then they will have to be in the queue until thread is available.
newCachedThreadPool:
This method returns an unbounded thread pool. It doesn’t have maximum size but if it has less number of tasks, then it will tear down unused thread. If thread has been unused for 1 mins(keepAliveTime), then it will tear it down.
newSingleThreadedExecutor:
This method returns an executor which is guaranteed to use the single thread.
newScheduledThreadPool:
This method returns a fixed size thread pool that can schedule commands to run after a given delay, or to execute periodically.
Using constructor of ThreadPoolExecutor:
If you want to customize creation of ThreadPoolExecutor, you can use its constructors too.

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue ,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) ;
  • corePoolSize: corePoolSize is the number of threads to keep in the pool, even if they are idle
  • MaximumPoolSize: the maximum number of threads to allow in the pool
  • keepAliveTime: When you have more threads already available than corePoolSize, then keepAliveTime is time upto which that thread will wait for task before terminating.
  • unit: time unit is for keepAliveTime
  • workQueue: workQueue is the BlockingQueue which holds the tasks before execution.
  • threadFactory: Factory which is used to create a new Thread.
  • handler : RejectedExecutionHandler which is used in case execution is block or queue is full
Interesting point about Executor framework is that, it is based on Producer consumer design pattern, where application thread produces task and worker thread consumers or execute those task, So it also suffers with limitation of Producer consumer task like if production speed is substantially higher than consumption than you may run OutOfMemory because of queued task, of course only if your queue is unbounded
Example of Thread Pool in Java
  • Below is an example of Thread pool in Java, which uses Executor framework of Java 5 to create a fixed size thread pool with a number of worker thread as 10.
  • It is pretty easy because of static factory methods provided by Executors class.
  • All we need to do is define our task which we want to execute concurrently and than submit that task to ExecutorService.
  • Thread pool will take care of how to execute that task
Here ExecutorService is very important. I will Put a separate blog on it.
First Basic Example for Thread Pool
package com.sks.softsolution.example3;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExample {

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 20; i++) {
            service.submit(new ThreadPoolExample().new Task(i));
        }

        service.shutdown();
        try {
            service.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
        }

    }

    final class Task implements Runnable {
        private int taskId;

        public Task(int id) {
            this.taskId = id;
        }

        @Override
        public void run() {
            System.out.println("Task ID : " + this.taskId + " performed by " + Thread.currentThread().getName());
        }

    }
}
2nd Example on thread Pool
package com.sks.softsolution.example3;
public class FetchDataFromFile implements Runnable {

    private final String fileName;

    public FetchDataFromFile(String fileName) {
        super();
        this.fileName = fileName;
    }

    @Override
    public void run() {
        try {
            System.out.println("Fetching data from " + fileName + " by " + Thread.currentThread().getName());
            Thread.sleep(5000); // Reading file
            System.out.println("Read file successfully: " + fileName + " by " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getFileName() {
        return fileName;
    }
}
package com.sks.softsolution.example3;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class RejectTaskHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        FetchDataFromFile ffdf = (FetchDataFromFile) r;
        System.out.println("Sorry!! We won't be able to read :" + ffdf.getFileName());
    }
}
package com.sks.softsolution.example3;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MainClassForThreadPoolExecutor {

    public static void main(String[] args) {

        // Wait queue is used to store waiting task
        BlockingQueue queue = new LinkedBlockingQueue(4);

        // Thread factory to create new threads
        ThreadFactory threadFactory = Executors.defaultThreadFactory();

        // Rejection handler in case task get rejected
        RejectTaskHandler rth = new RejectTaskHandler();
        // ThreadPoolExecutor constructor to create its instance
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 10L, TimeUnit.MILLISECONDS, queue,
                threadFactory, rth);
        for (int i = 1; i <= 10; i++) {
            FetchDataFromFile fdff = new FetchDataFromFile("File " + i);
            System.out.println("A new file has been added to read : " + fdff.getFileName());
            // Submitting task to executor
            threadPoolExecutor.execute(fdff);
        }
        threadPoolExecutor.shutdown();

    }
}
Benefits of Thread Pool in Java
Thread Pool offers several benefit to Java application, biggest of them is separating submission of a task to execution of the task ,which results if more loose coupled and flexible design than tightly coupled create and execute pattern.
Here are some benefits of using Thread pool in Java:
  1. Use of Thread Pool reduces response time by avoiding thread creation during request or task processing.
  2. Use of Thread Pool allows you to change your execution policy as you need. you can go from single thread to multiple threads by just replacing ExecutorService implementation.
  3. Thread Pool in Java application increases the stability of the system by creating a configured number of threads decided based on system load and available resource.
Thanks
Happy Coding !!!
Please provide your feedback.

0 komentar:

Posting Komentar

 
[tutup]