Java Thread Pool Example using Executors and ThreadPoolExecutor
2013-11-20 00:00
701 查看
A thread pool manages the pool of worker threads, it contains a queue that keeps tasks waiting to get executed. A thread pool manages the collection of Runnable threads and worker threads execute Runnable from the queue.
java.util.concurrent.Executors
provide implementation of
java.util.concurrent.Executor
interface to create the thread pool in java.
Let’s write a simple program to explain it’s working.
First we need to have a Runnable class.
Here is the test program where we are creating fixed thread pool from Executors framework.
In above program, we are creating fixed size thread pool of 5 worker threads. Then we are submitting 10 jobs to this pool, since the pool size is 5, it will start working on 5 jobs and other jobs will be in wait state, as soon as one of the job is finished, another job from the wait queue will be picked up by worker thread and get’s executed.
Here is the output of the above program.
The output confirms that there are five threads in the pool named from “pool-1-thread-1? to “pool-1-thread-5? and they are responsible to execute the submitted tasks to the pool.
Executors class provide simple implementation of ExecutorService using ThreadPoolExecutor but ThreadPoolExecutor provides much more feature than that. We can specify the number of threads that will be alive when we create ThreadPoolExecutor instance and we can limit the size of thread pool and create our own RejectedExecutionHandler implementation to handle the jobs that can’t fit in the worker queue.
Here is our custom implementation of RejectedExecutionHandler interface.
ThreadPoolExecutor provides several methods using which we can find out the current state of executor, pool size, active thread count and task count. So I have a monitor thread that will print the executor information at certain time interval.
Here is the thread pool implementation example using ThreadPoolExecutor.
Notice that while initializing the ThreadPoolExecutor, we are keeping initial pool size as 2, maximum pool size to 4 and work queue size as 2. So if there are 4 running tasks and more tasks are submitted, the work queue will hold only 2 of them and rest of them will be handled by RejectedExecutionHandlerImpl.
Here is the output of above program that confirms above statement.
Notice the change in active, completed and total completed task count of the executor. We can invoke shutdown() method to finish execution of all the submitted tasks and terminate the thread pool.
Reference: Java Thread Pool Example using Executors and ThreadPoolExecutor from our JCG partner Pankaj Kumar at the Developer Recipes blog.
java.util.concurrent.Executors
provide implementation of
java.util.concurrent.Executor
interface to create the thread pool in java.
Let’s write a simple program to explain it’s working.
First we need to have a Runnable class.
01 | package com.journaldev.threadpool; |
02 |
03 | public class WorkerThread implements Runnable { |
04 |
05 | private String command; |
06 |
07 | public WorkerThread(String s){ |
08 | this.command=s; |
09 | } |
10 |
11 | @Override |
12 | public void run() { |
13 | System.out.println(Thread.currentThread().getName()+' Start. Command = '+command); |
14 | processCommand(); |
15 | System.out.println(Thread.currentThread().getName()+' End.'); |
16 | } |
17 |
18 | private void processCommand() { |
19 | try { |
20 | Thread.sleep(5000); |
21 | } catch (InterruptedException e) { |
22 | e.printStackTrace(); |
23 | } |
24 | } |
25 |
26 | @Override |
27 | public String toString(){ |
28 | return this.command; |
29 | } |
30 | } |
01 | package com.journaldev.threadpool; |
02 |
03 | import java.util.concurrent.ExecutorService; |
04 | import java.util.concurrent.Executors; |
05 |
06 | public class SimpleThreadPool { |
07 |
08 | public static void main(String[] args) { |
09 | ExecutorService executor = Executors.newFixedThreadPool(5); |
10 | for (int i = 0; i < 10; i++) { |
11 | Runnable worker = new WorkerThread('' + i); |
12 | executor.execute(worker); |
13 | } |
14 | executor.shutdown(); |
15 | while (!executor.isTerminated()) { |
16 | } |
17 | System.out.println('Finished all threads'); |
18 | } |
19 |
20 | } |
Here is the output of the above program.
01 | pool-1-thread-2 Start. Command = 1 |
02 | pool-1-thread-4 Start. Command = 3 |
03 | pool-1-thread-1 Start. Command = 0 |
04 | pool-1-thread-3 Start. Command = 2 |
05 | pool-1-thread-5 Start. Command = 4 |
06 | pool-1-thread-4 End. |
07 | pool-1-thread-5 End. |
08 | pool-1-thread-1 End. |
09 | pool-1-thread-3 End. |
10 | pool-1-thread-3 Start. Command = 8 |
11 | pool-1-thread-2 End. |
12 | pool-1-thread-2 Start. Command = 9 |
13 | pool-1-thread-1 Start. Command = 7 |
14 | pool-1-thread-5 Start. Command = 6 |
15 | pool-1-thread-4 Start. Command = 5 |
16 | pool-1-thread-2 End. |
17 | pool-1-thread-4 End. |
18 | pool-1-thread-3 End. |
19 | pool-1-thread-5 End. |
20 | pool-1-thread-1 End. |
21 | Finished all threads |
Executors class provide simple implementation of ExecutorService using ThreadPoolExecutor but ThreadPoolExecutor provides much more feature than that. We can specify the number of threads that will be alive when we create ThreadPoolExecutor instance and we can limit the size of thread pool and create our own RejectedExecutionHandler implementation to handle the jobs that can’t fit in the worker queue.
Here is our custom implementation of RejectedExecutionHandler interface.
01 | package com.journaldev.threadpool; |
02 |
03 | import java.util.concurrent.RejectedExecutionHandler; |
04 | import java.util.concurrent.ThreadPoolExecutor; |
05 |
06 | public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler { |
07 |
08 | @Override |
09 | public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { |
10 | System.out.println(r.toString() + ' is rejected'); |
11 | } |
12 |
13 | } |
01 | package com.journaldev.threadpool; |
02 |
03 | import java.util.concurrent.ThreadPoolExecutor; |
04 |
05 | public class MyMonitorThread implements Runnable |
06 | { |
07 | private ThreadPoolExecutor executor; |
08 |
09 | private int seconds; |
10 |
11 | private boolean run=true; |
12 |
13 | public MyMonitorThread(ThreadPoolExecutor executor, int delay) |
14 | { |
15 | this.executor = executor; |
16 | this.seconds=delay; |
17 | } |
18 |
19 | public void shutdown(){ |
20 | this.run=false; |
21 | } |
22 |
23 | @Override |
24 | public void run() |
25 | { |
26 | while(run){ |
27 | System.out.println( |
28 | String.format('[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s', |
29 | this.executor.getPoolSize(), |
30 | this.executor.getCorePoolSize(), |
31 | this.executor.getActiveCount(), |
32 | this.executor.getCompletedTaskCount(), |
33 | this.executor.getTaskCount(), |
34 | this.executor.isShutdown(), |
35 | this.executor.isTerminated())); |
36 | try { |
37 | Thread.sleep(seconds*1000); |
38 | } catch (InterruptedException e) { |
39 | e.printStackTrace(); |
40 | } |
41 | } |
42 |
43 | } |
44 | } |
01 | package com.journaldev.threadpool; |
02 |
03 | import java.util.concurrent.ArrayBlockingQueue; |
04 | import java.util.concurrent.Executors; |
05 | import java.util.concurrent.ThreadFactory; |
06 | import java.util.concurrent.ThreadPoolExecutor; |
07 | import java.util.concurrent.TimeUnit; |
08 |
09 | public class WorkerPool { |
10 |
11 | public static void main(String args[]) throws InterruptedException{ |
12 | //RejectedExecutionHandler implementation |
13 | RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl(); |
14 | //Get the ThreadFactory implementation to use |
15 | ThreadFactory threadFactory = Executors.defaultThreadFactory(); |
16 | //creating the ThreadPoolExecutor |
17 | ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, newArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler); |
18 | //start the monitoring thread |
19 | MyMonitorThread monitor = new MyMonitorThread(executorPool, 3); |
20 | Thread monitorThread = new Thread(monitor); |
21 | monitorThread.start(); |
22 | //submit work to the thread pool |
23 | for(int i=0; i<10; i++){ |
24 | executorPool.execute(new WorkerThread('cmd'+i)); |
25 | } |
26 |
27 | Thread.sleep(30000); |
28 | //shut down the pool |
29 | executorPool.shutdown(); |
30 | //shut down the monitor thread |
31 | Thread.sleep(5000); |
32 | monitor.shutdown(); |
33 |
34 | } |
35 | } |
Here is the output of above program that confirms above statement.
01 | pool-1-thread-1 Start. Command = cmd0 |
02 | pool-1-thread-4 Start. Command = cmd5 |
03 | cmd6 is rejected |
04 | pool-1-thread-3 Start. Command = cmd4 |
05 | pool-1-thread-2 Start. Command = cmd1 |
06 | cmd7 is rejected |
07 | cmd8 is rejected |
08 | cmd9 is rejected |
09 | [monitor] [0/2] Active: 4, Completed: 0, Task: 6, isShutdown: false, isTerminated: false |
10 | [monitor] [4/2] Active: 4, Completed: 0, Task: 6, isShutdown: false, isTerminated: false |
11 | pool-1-thread-4 End. |
12 | pool-1-thread-1 End. |
13 | pool-1-thread-2 End. |
14 | pool-1-thread-3 End. |
15 | pool-1-thread-1 Start. Command = cmd3 |
16 | pool-1-thread-4 Start. Command = cmd2 |
17 | [monitor] [4/2] Active: 2, Completed: 4, Task: 6, isShutdown: false, isTerminated: false |
18 | [monitor] [4/2] Active: 2, Completed: 4, Task: 6, isShutdown: false, isTerminated: false |
19 | pool-1-thread-1 End. |
20 | pool-1-thread-4 End. |
21 | [monitor] [4/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
22 | [monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
23 | [monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
24 | [monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
25 | [monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
26 | [monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false |
27 | [monitor] [0/2] Active: 0, Completed: 6, Task: 6, isShutdown: true, isTerminated: true |
28 | [monitor] [0/2] Active: 0, Completed: 6, Task: 6, isShutdown: true, isTerminated: true |
Reference: Java Thread Pool Example using Executors and ThreadPoolExecutor from our JCG partner Pankaj Kumar at the Developer Recipes blog.
相关文章推荐
- 【Java多线程】之十二:Java Thread Pool Example using Executors and ThreadPoolExecutor
- java 多线程之Executors.newFixedThreadPool
- java 通过Executors.newFixedThreadPool创建固定大小的线程执行器
- Java Thread wait, notify and notifyAll Example
- Dead simple example of using Multiprocessing Queue, Pool and Locking
- Java Lock and Condition Example using Producer Consumer Solution
- Java自带的线程池Executors.newFixedThreadPool
- Java 自带的线程池Executors.newFixedThreadPool
- ThreadLocal in Java - Example Program and Tutorial
- [Java并发编程(二)] 线程池 FixedThreadPool、CachedThreadPool、ForkJoinPool?为后台任务选择合适的 Java executors
- Java 自带的线程池Executors.newFixedThreadPool
- Spring and Java Thread example
- Java Fork and Join using ForkJoinPool
- Java并发包:Java Fork and Join using ForkJoinPool
- Java 自带的线程池Executors.newFixedThreadPool
- java ThreadPool
- Difference between throw and throws in Exception handling - Java Example
- Exception in thread "pool-1-thread-15" java.lang.OutOfMemoryError: Java heap space
- android Executors.newFixedThreadPool和newCachedThreadPool区别
- Java性能优化学习之 巧用线程池ThreadPool