2. 3. Introduction to the testing class Thread PoolThe basic idea of the thread pool is the idea of an object pool. It first opens up a piece of memory space and opens many threads waiting for tasks, once a task exists, the thread in the thread pool is used for the task. After the task ends, the thread is placed in the thread pool. The execution scheduling in the pool is managed by the thread pool manager.
Thread Pool FunctionThe role of the thread pool is to better manage the threads in the system. The number of threads can be set automatically or manually based on the system environment to achieve the best running effect.
Advantages of Thread PoolWhat are the advantages of using a thread pool over not using a thread pool?
This reduces the number of times threads are created and destroyed. Each worker thread can be reused after use. The thread pool size can be controlled freely based on system capabilities, prevent the server from consuming too much memory and downtime when the thread pool is not used and the thread is not well managedJava. util. after the concurrent package, the thread pool is greatly optimized. Now we only need to use the provided API, we can easily use the built-in JDK thread pool, it provides great convenience for us to write our own programs.
ThreadPoolExecutorLet's take a look at the complete construction method of ThreadPoolExecutor.
1 |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
|
The parameter meanings are as follows:
CorePoolSize-Number of threads stored in the pool, including Idle threads. MaximumPoolSize-Maximum number of threads allowed in the pool. KeepAliveTime-when the number of threads exceeds the core, this is the maximum time for Idle threads to wait for new tasks before termination. Unit-keepAliveTime parameter time unit. WorkQueue-the queue used to keep the task before execution. This queue only keeps Runnable tasks submitted by the execute method. ThreadFactory-the factory used by the execution program to create a new thread. Handler-the handler used to block execution because it exceeds the thread range and queue capacity.
The following describes some common thread pools:
NewSingleThreadExecutor: Create a single-threaded thread pool. This thread pool only has one thread working, which is equivalent to a single thread serial execution of all tasks. If this unique thread ends due to an exception, a new thread will replace it. This thread pool ensures that all tasks are executed in the order they are submitted.
Corresponding Constructor
123456 |
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue
())); }
|
Example
12345678 |
// Create a single-threaded thread pool ExecutorService pool = Executors. newSingleThreadExecutor (); // creates and implements the Runnable interface object. Of course, the Thread object also implements the Runnable interface Thread t1 = new MyThread (); // puts the Thread into the pool to execute pool.exe cute (t1 ); // close the thread pool. shutdown (); |
NewFixedThreadPool: Create a fixed thread pool. Each time a task is submitted, a thread is created until the thread reaches the maximum size of the thread pool. The size of the thread pool remains unchanged once it reaches the maximum value. If a thread ends due to an execution exception, the thread pool will add a new thread.
Corresponding Constructor
12345 |
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue
()); }
|
Example
12345678 |
// Create a thread pool that can reuse a fixed number of threads ExecutorService pool = Executors. newFixedThreadPool (2); // create and implement the Runnable interface object. Of course, the Thread object also implements the Runnable interface Thread t1 = new MyThread (); // put the Thread into the pool and execute pool.exe cute (t1 ); // close the thread pool. shutdown (); |
NewCachedThreadPool: Create a cacheable unbounded thread pool. If the thread pool size exceeds the thread required to process the task, some Idle threads (not executed in 60 seconds) will be reclaimed. When the number of tasks increases, this thread pool can intelligently add new threads to process tasks. This thread pool does not limit the thread pool size. The thread pool size depends entirely on the maximum thread size that can be created by the operating system (or JVM.
Corresponding Constructor
12345 |
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue
()); }
|
Example
12345678 |
// Create a thread pool where new threads can be created as needed, but ExecutorService pool = Executors will be reused when previously constructed threads are available. newCachedThreadPool (); // creates and implements the Runnable interface object. Of course, the Thread object also implements the Runnable interface Thread t1 = new MyThread (); // puts the Thread into the pool to execute pool.exe cute (t1 ); // close the thread pool. shutdown (); |
NewScheduledThreadPool: Creates an infinite thread pool. This thread pool supports regular and periodic task execution requirements.
Example
1234567891011 |
//// Create a thread pool that can be scheduled to run commands or periodically after a given delay. ExecutorService pool = Executors. newScheduledThreadPool (2); // creates and implements the Runnable interface object. Of course, the Thread object also implements the Runnable interface Thread t1 = new MyThread (); Thread t2 = new MyThread (); // Add the thread to the pool to execute pool.exe cute (t1); // use the delayed execution method pool. schedule (t2, 10, TimeUnit. MILLISECONDS); // closes the thread pool. shutdown (); |
Self-made Thread PoolNow let's write a thread pool by ourselves. This is just a simple thread pool that helps us better understand the principles of the thread pool.
Thread Pool subject classMyThread. java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
Import java. util. handler list;/***** @ author zlk * thread pool, inheriting ThreadGroup. ThreadGroup is used to process classes of a group of threads. It is a tree structure, its lower-level nodes can still be ThreadGroup objects */public class MyThreadPool extends ThreadGroup {private boolean isAlive; // It indicates whether the thread pool has enabled private writable list taskQueue; // private int threadID of the task queue in the thread pool; // thread ID in the thread pool private static int threadPoolID; // thread pool ID/*** create a new thread pool, numThreads is the number of threads in the pool * @ param numThreads */public MyThreadPool (int NumThreads) {super ("ThreadPool-" + (threadPoolID ++); // you can specify true as the daemon attribute for the thread pool, indicates that when all threads in the thread pool are destroyed, the thread pool is automatically destroyed. Super. setDaemon (true); this. isAlive = true; // create a task queue this. taskQueue = new worker list (); // start numThreads working threads for (int I = 0; I <numThreads; I ++) {new PooledThread (). start () ;}}/*** add new task * @ param Task */public synchronized void merge mtask (task) {if (! This. isAlive) {// throw the IllegalStateException exception throw new IllegalStateException ();} if (task! = Null) {// put the task at the end of the task queue this. taskQueue. add (task); // notify the worker thread to obtain the notify () ;}/ *** obtain the Task */protected synchronized task getTask () throws InterruptedException {// if the task list is empty and the thread pool is not closed, wait for the task while (this. taskQueue. size () = 0) {if (! This. isAlive) {return null;} wait () ;}// retrieve the first Task return (Task) this in the Task list. taskQueue. removeFirst ();}/*** close the thread pool. All threads stop and no longer execute the task */public synchronized void forceclose () {if (isAlive) {this. isAlive = false; // clear the task this. taskQueue. clear (); // terminate all threads in the thread pool this. interrupt () ;}}/*** close the thread pool and wait until all tasks in the thread pool are completed, but new tasks cannot be accepted */public void shutdown () {// notify other waiting threads that the message synchronized (this) {isAlive = fal "this thread pool has been closed" Se; y () ;}/// wait for all threads to finish. // create a new thread array first. The activeCount method gets the estimated number of active threads in the Thread pool. Thread [] threads = new Thread [this. activeCount ()]; // copy the active threads in the thread pool to the newly created thread array. int count = this. enumerate (threads); for (int I = 0; I <count; I ++) {try {// wait until the thread stops running threads [I]. join ();} catch (InterruptedException e) {e. printStackTrace () ;}}/ *** internal class, used to execute the task's working Thread */private class PooledThread extends Thread {// constructor public PooledThread () {// The first parameter is the object in the thread group of the thread, that is, the pair of the current thread pool Image // The second parameter is the thread name super (MyThreadPool. this, "PooledThread-" + (threadID ++);} public void run () {// If the thread is not terminated while (! IsInterrupted () {// obtain Task task = null; try {Task = getTask ();} catch (InterruptedException e) {e. printStackTrace ();} // as long as the task list in the thread pool is not empty, the getTask method can always get a task. // If getTask () returns null, it indicates that there are no tasks in the thread pool and the thread pool has been closed. If (task = null) {return;} // run the task and absorb exceptions. try {task. perform ();} catch (Throwable t) {// when a thread in the thread group has an uncaptured exception, the JVM will go back and call the uncaughtException method uncaughtException (this, t );}}}}} |
Task TypeTask. java// Serves as the total interface for executing tasks
1234567 |
Public interface Task {/*** execution Task * throws Exception possible exceptions during execution */public void perform () throws Exception ;} |
MyTask. java// Implement the task interface
123456789101112131415161718192021222324 |
Public class MyTask implements Task {private int taskID = 0; // Task ID public MyTask (int id) {this. taskID = id;}/*** perform method for implementing the Task interface */@ Override public void perform () throws Exception {System. out. println ("MyTask" + taskID + ": start"); // sleep for one second try {Thread. sleep (1000);} catch (Exception e) {e. printStackTrace ();} System. out. println ("MyTask" + taskID + ": end ");}} |
Test classPoolTest. java// Test the self-made Thread Pool
1234567891011121314151617181920 |
Import com. zale. threadpool. myTask; import com. zale. threadpool. myThreadPool; public class PoolTest {public static void main (String [] args) {int numThreads = 3; // Number of threads in the thread pool MyThreadPool threadPool = new MyThreadPool (numThreads ); // generate the thread pool int numTasks = 10; // number of tasks // run the task for (int I = 0; I <numTasks; I ++) {threadPool. performTask (new MyTask (I);} // close the thread pool and wait for all tasks to complete threadPool. shutdown ();}} |