Recently, when I was writing a Java program, I encountered some multithreading and used the thread pool in Java. JDK provides comprehensive support for thread pools. In the java. util. concurrent package, the ThreadPoolExecuter class is used to represent a thread pool, and an Executor class plays the role of the thread pool factory. For example:
| The code is as follows: |
Copy code |
Public static ExecutorService newFixedThreadPool (int nThreads)
Public static ExecutorService newSingleThreadExecutor ()
Public static ExecutorService newCachedThreadPool ()
...
|
Essentially, these factory methods call the constructor of the ThreadPoolExecutor class:
| The code is as follows: |
Copy code |
Public ThreadPoolExecutor (int corePoolSize,
Int maximumPoolSize,
Long keepAliveTime,
TimeUnit unit,
BlockingQueue <Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
|
The parameter description is as follows:
CorePoolSize: number of threads in the thread pool, even if the thread is idle
MaximumPoolSize: maximum number of threads in the thread pool
KeepAliveTime: when the number of threads is greater than corePoolSize, specify how long the idle thread will be destroyed
Unit: The unit of keepAliveTime.
WorkQueue: task queue submitted but not executed
ThreadFactory: thread factory
Handler: Denial Policy
Implementation
From the ThreadPoolExecutor constructor, we probably know what is needed to implement a thread pool. If we fully follow the parameters in the constructor, it is too troublesome and there are too many things to consider, therefore, a simple version is implemented.
First, consider how many threads are stored in the thread pool. You can simply specify a variable and put these threads in a container to facilitate destruction and to know their status.
Then we need to consider a container as a task queue. If there are five threads in the thread pool and all five threads are in the working state, the sent tasks need to be placed in the task queue for waiting.
Finally, it is the form of working threads in the thread pool. A worker thread should be started at the time of creation. The main task is to retrieve the infinite loop of task-execution task from the task queue.
One way of implementing a working thread:
| The code is as follows: |
Copy code |
|
Class WorkerThread extends Thread {
Private Boolean isRunning = true;
Public void close (){
IsRunning = false;
}
Public void run (){
While (isRunning ){
Runnable task = null;
Try {
Task = taskQueue. take ();
} Catch (InterruptedException e ){
E. printStackTrace ();
}
Task. run ();
}
}
} |
WorkerThread is an internal class of the thread pool, where taskQueue is a task queue. Here we use a BlockingQueue interface implementation, and both the put and take methods are blocked. The following table lists the task submission and destruction thread pools:
| The code is as follows: |
Copy code |
|
Public void submit (Runnable task ){
If (currentWorking () <limits ){
WorkerThread worker = new WorkerThread ();
Worker. start ();
Workers. add (worker );
}
Try {
TaskQueue. put (task );
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
Public void destroy (){
While (! TaskQueue. isEmpty ());
For (WorkerThread worker: workers ){
Worker. close ();
}
} |
The complete code is here.
| The code is as follows: |
Copy code |
|
Import java. util. ArrayList;
Import java. util. concurrent. BlockingQueue;
Import java. util. concurrent. Define blockingqueue;
/**
* Created by rahul on 7/20/16.
*/
Public class SimpleThreadPool {
Public static BlockingQueue <Integer> testQueue = new LinkedBlockingQueue <> ();
Private int limits;
Private ArrayList <WorkerThread> workers;
Private BlockingQueue <Runnable> taskQueue;
SimpleThreadPool (int nums ){
Limits = nums;
Workers = new ArrayList <> ();
TaskQueue = new LinkedBlockingQueue <> ();
}
Private int currentWorking (){
Return workers. size ();
}
Public void submit (Runnable task ){
If (currentWorking () <limits ){
WorkerThread worker = new WorkerThread ();
Worker. start ();
Workers. add (worker );
}
Try {
TaskQueue. put (task );
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
Public void destroy (){
While (! TaskQueue. isEmpty ());
For (WorkerThread worker: workers ){
Worker. close ();
}
}
Class WorkerThread extends Thread {
Private Boolean isRunning = true;
Public void close (){
IsRunning = false;
}
Public void run (){
While (isRunning ){
Runnable task = null;
Try {
Task = taskQueue. take ();
} Catch (InterruptedException e ){
E. printStackTrace ();
}
Task. run ();
}
}
}
Public static void main (String [] args ){
SimpleThreadPool pool = new SimpleThreadPool (10 );
For (int I = 0; I <100; ++ I ){
Pool. submit (new test ("Task" + I ));
}
Pool. destroy ();
}
}
Class test implements Runnable {
Private String id;
Public test (String str) {id = str ;}
Public void run (){
Try {
System. out. println ("Start process" + id );
Thread. sleep (1000 );
System. out. println (id + "Completed! ");
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
} |
The thread pool seems simple and complex, because there are many things to consider if you really want to reach the application level, such as when to start a thread and when the thread should be suspended, task Queue blocking and timeout, task denial policy, thread lifecycle, and so on. As for the thread pool implemented in this article