2404. Java Concurrency - Thread PoolExecutors and ExecutorService
Create fixed thread pool and scheduled thread pool.
1. Thread Pool
1.1 What is Thread Pool?
Thread Pools are useful when you need to limit the number of threads running in your application at the same time. There is a performance overhead associated with starting a new thread, and each thread is also allocated some memory for its stack etc.
Instead of starting a new thread for every task to execute concurrently, the task can be passed to a thread pool. As soon as the pool has any idle threads the task is assigned to one of them and executed. Internally the tasks are inserted into a Blocking Queue
which the threads in the pool are dequeuing from. When a new task is inserted into the queue one of the idle threads will dequeue it successfully and execute it. The rest of the idle threads in the pool will be blocked waiting to dequeue tasks.
1.2 Interface and Class
Java 5 comes with built in thread pools in the java.util.concurrent
package, so you don’t have to implement your own thread pool. Below are the important interfaces and classes for using thread pool.
- Interface
Executor
- Interface
ExecutorService
- Class
Executors
- Class
ThreadPoolExecutor
1.3 Types of Thread Pool
Class Executors
supports to create five types of thread pool with corresponding factory methods. You can choose any of them based to your requirement.
Method | Description |
---|---|
newCachedThreadPool | New threads are created as needed; idle threads are kept for 60 seconds. |
newFixedThreadPool | The pool contains a fixed set of threads; idle threads are kept indefinitely. |
newSingleThreadExecutor | A “pool” with a single thread that executes the submitted tasks sequentially (similar to the Swing event dispatch thread). |
newScheduledThreadPool | A fixed-thread pool for scheduled execution; a replacement for java.util.Timer. |
newSingleThreadScheduledExecutor | A single-thread “pool” for scheduled execution. |
2. Examples
2.1 Fixed Thread Pool
Create task thread by implementing Runnable interface. It takes random seconds to run the task.
public class FixedTask implements Runnable {
private String name;
public FixedTask(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void run() {
try {
Long duration = (long) (Math.random() * 10);
System.out.println("Executing: " + name + " at " + LocalDateTime.now().toString());
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Create a fixed thread pool which has two numbers of thread in the pool. We can use it as either ExecutorService
interface or ThreadPoolExecutor
class. Then, we create 5 tasks and submit them to thread pool.
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPoolExample {
public static void main(String[] args)
{
//ExecutorService executor = Executors.newFixedThreadPool(2);
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(2);
for (int i = 1; i <= 5; i++)
{
Task task = new Task("Task " + i);
System.out.println("Created : " + task.getName());
executor.submit(task);
}
executor.shutdown();
}
}
Output.
Created: Task 1
Created: Task 2
Created: Task 3
Created: Task 4
Created: Task 5
Executing: Task 2 at 2019-03-27T10:02:32.272
Executing: Task 1 at 2019-03-27T10:02:32.272
Executing: Task 3 at 2019-03-27T10:02:33.324
Executing: Task 4 at 2019-03-27T10:02:38.321
Executing: Task 5 at 2019-03-27T10:02:39.327
2.2 Scheduled Thread Pool
We can create scheduled thread pool to run a task periodically.
Create task thread by implementing Runnable interface.
public class ScheduledTask implements Runnable {
private String name;
public ScheduledTask(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void run() {
System.out.println("Executing: " + name + " at " + LocalDateTime.now().toString());
}
}
Create a scheduled thread pool which has only one thread in the pool. The task is scheduled to run every 3 seconds.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args)
{
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
ScheduledTask task = new ScheduledTask("Scheduled Task");
ses.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
}
}
Output.
Executing: Scheduled Task at 2019-03-28T09:23:58.476
Executing: Scheduled Task at 2019-03-28T09:24:01.444
Executing: Scheduled Task at 2019-03-28T09:24:04.445
Executing: Scheduled Task at 2019-03-28T09:24:07.441
Executing: Scheduled Task at 2019-03-28T09:24:10.442
Executing: Scheduled Task at 2019-03-28T09:24:13.445
Executing: Scheduled Task at 2019-03-28T09:24:16.444
...