Hello, today I share the Java thread pool with you. Take out your little book and write it down.
The thread pool
1. What is it?
The job of the thread pool is to control the number of threads running, queue tasks in the process, and then start those tasks after the thread is created. If the number of threads exceeds the maximum number, the exceeding number of threads queue up, wait for other threads to complete, and then pull the task from the queue to execute.
Its main characteristics are: thread reuse; Control the maximum number of concurrent requests; Management of thread
Advantages of thread pools:
First: reduce resource consumption. Reduce the cost of thread creation and destruction by reusing created threads.
Second: improve response speed. When a task arrives, it can execute immediately without waiting for a thread to be created.
Third: improve thread manageability. Threads are scarce resources. If they are created without limit, they will not only consume system resources, but also reduce system stability. Thread pools can be used for unified allocation, tuning, and monitoring.
2. How to use it?
Thread pooling in Java is implemented through the Executor framework,
The framework uses Executor, Executors, ExecutorService, and ThreadPoolExecutor classes
Block diagram:
3, implementation,
Java has its own implementation of several thread pools, respectively:
1, Executors. NewFixedThreadPool (int)
It is better to create a pool of N threads with a fixed number of threads
2, Executors. NewSingleThreadExecutor ()
Task by task execution, pool by thread
3, Executors. NewCachedThreadPool ()
Many short-term asynchronous tasks are performed, and the thread pool creates new threads as needed, but reuses previously built threads as they become available. Can expand, encounter strong is strong
Example:
public class TestThreadPool {
Public static void main (String [] args) {/ / a thread pool are available in 5 thread calls the ExecutorService threadPool = Executors. NewFixedThreadPool (5); / / a thread pool is only one thread can call the ExecutorService threadPool1 = Executors. NewSingleThreadExecutor (); / / a thread pool can have n thread can call, can increase the ExecutorService threadPool2 = Executors. NewCachedThreadPool (); try { for (int i = 0; i < 10; I++) {threadpool2.execute (() -> {system.out.println (thread.currentthread ().getname () + "\t "); }); } } catch (Exception e) { e.printStackTrace(); } finally { threadPool.shutdown(); }}Copy the code
}
Underlying principles:
Seven parameters:
CorePoolSize: The number of resident core threads in the thread pool
MaximumPoolSize: The maximum number of concurrent threads in the thread pool, which must be greater than or equal to 1 (for customization, set this to the number of logical processors on the CPU plus 1)
Runtime.getruntime ().availableProcessors()
KeepAliveTime: When the number of threads in the current pool exceeds corePoolSize, when the keepAliveTime reaches keepAliveTime, the excess threads are destroyed until only corePoolSize remains
Unit: keepAliveTime unit
WorkQueue: Queue of tasks that have been submitted but not yet executed
ThreadFactory: represents a threadFactory that generates worker threads in the thread pool and is used to create threads, usually the default. Executors.defaultThreadFactory()
Handler: A rejection policy that specifies how to reject runnable requests when the queue is full and the number of worker threads is greater than or equal to the maximum thread pool size (maximumPoolSize)
All three methods call this method to get the thread pool
/ * *
-
CorePoolSize: The number of resident core threads in the thread pool
-
MaximumPoolSize: The maximum number of threads in the program pool that can hold simultaneous execution
-
KeepAliveTime: When the idle time reaches keepAliveTime, the excess threads are destroyed until only corePoolSize remains
-
Unit: keepAliveTime unit
-
WorkQueue: Queue of tasks that have been submitted but not yet executed
* /
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
Copy the code
Handler rejection policy in parameters:
AbortPolicy (default) : direct selling RejectedExecutionException exception to prevent normal operation of system. new ThreadPoolExecutor.AbortPolicy()
CallerRunsPolicy: CallerRuns “is an adjustment mechanism that neither abandons the task nor throws an exception, but instead rolls some tasks back to the caller, reducing traffic to the new task. (Redundant tasks are also executed, reverted back to the caller)
DiscardOldestPolicy: Discards the longest waiting task in the queue and then adds the current task to the queue to try to commit the current task again.
DiscardPolicy: This policy silently discards unhandled tasks without processing or throwing exceptions. This is the best strategy if you allow tasks to be lost.
Processing logic:
(Identify core threads first, then blocking queues, then thread pools)
After the thread pool is created, wait for the request. When the execute() method is called to add a request task, the thread pool makes the following judgments:
If the number of running threads is smaller than corePoolSize, create a thread to run the task immediately.
If the number of running threads is greater than or equal to corePoolSize, queue the task;
If the queue is full and the number of running threads is less than maximumPoolSize, create a non-core thread to run the task immediately.
If the queue is full and the number of running threads is greater than or equal to maximumPoolSize, the thread pool will start a saturation denial policy to execute.
When a thread completes a task, it takes the next task from the queue and executes it.
When a thread has nothing to do for more than a certain amount of time, the thread decides:
If the number of threads currently running is greater than corePoolSize, the thread is stopped.
So after all the tasks of the thread pool are completed, it will eventually shrink to the size of corePoolSize.
Use Executors to create thread pools. Instead, customize ThreadPoolExecutor by setting 7 parameters.
There are several reasons why you don’t use the JDK’s built-in methods for creating thread pools:
FixedThreadPool and SingleThreadPool:
The allowed queue length is integer. MAX_VALUE, which may accumulate a large number of requests and result in OOM
CachedThreadPool and ScheduledThreadPool:
The number of threads allowed to be created is integer.max_value, which may create a large number of requests, resulting in OOM thread pool exception catching
4. Exception handling
1, thread exception handling The java.lang.Runnable interface for tasks performed by threads in Java requires that no Checked exceptions be thrown.
Usually the java.lang.Thread object runs with a default exception handling method set:
java.lang.Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)
The default static global exception catch method outputs the stack.
Of course, we can override this default implementation, just customize it
2. Thread pool exception handling
Thread pools are special. By default, the thread pool Java. Util. Concurrent. ThreadPoolExecutor will Catch all exceptions, when the task completes. The source code is as follows:
The ExecutionException exception is Java. Lang. Runnable or Java. Util. Concurrent. Callable throw exceptions.
That is, the thread pool catches all exceptions while executing the task and adds this exception to the result. All threads in the thread pool will then be unable to catch the exception thrown. This prevents intercepting error exceptions by setting the thread’s default catch method. There is also no custom thread to complete exception interception.
. Fortunately, the Java. Util. Concurrent ThreadPoolExecutor reserved a method, extended run in the task has been completed (of course also reserved a protected methods
BeforeExecute (Thread T, Runnable R) :
afterExecute(Runnable r, Throwable t)
protected void afterExecute(Runnable r, Throwable t) { }
The default implementation of this method is null so that we can achieve custom error handling by inheritance or overwriting ThreadPoolExecutor.
The following is an example:
. Therefore, the thread pool by overriding ThreadPoolExecutor afterExecute method, we can catch exceptions to the task (RuntimeException)
Well, today’s article is here, I hope to help you confused screen!