Why did Alibaba disable Executors to create thread pools? Thread pool does not allow to be created by Executors. / * ThreadPoolExecutor * does not allow thread pool to be created by Executors
Definition of thread pool
Manage a group of worker threads. Reusing threads through a thread pool has several advantages:
- Reduce resource creation => Reduce memory overhead and create threads occupy memory
- Reduce system overhead => It takes time to create threads, which delays processing of requests
- Improved stability => Avoid infinite thread creation caused
OutOfMemoryError
【 OOM for short 】
Create a thread pool by Executors
Creating thread pools based on the type of object returned can be divided into three categories:
- Create an object that returns ThreadPoolExecutor
- Create return ScheduleThreadPoolExecutor object
- Create a return ForkJoinPool object
ThreadPoolExecutor
Because these static methods of creating a thread pool return a ThreadPoolExecutor object, the difference between creating a ThreadPoolExecutor object manually is that we don’t need to pass the constructor arguments ourselves. ThreadPoolExecutor has four constructors, all of which end up calling the same one:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)Copy the code
Constructor parameter description:
- CorePoolSize => Number of core threads in the thread pool
- MaximumPoolSize => Maximum number of thread pools
- KeepAliveTime => keepAliveTime of idle threads
- Unit => Time unit
- WorkQueue => Buffer queue used by the thread pool
- ThreadFactory => The factory used by the thread pool to create threads
- Handler => Processing policy of the thread pool for rejected tasks
Thread pool execution logic and thread pool parameters
Execution logic description:
- Check whether the number of core threads is full, the size of the number of core threads and
corePoolSize
If no, a thread is created to execute the task - If the core thread pool is full, check whether the queue is full, whether the queue is full and
workQueue
If not, the queue is added - If the queue is full, determine whether the thread pool is full and whether the thread pool is full
maximumPoolSize
If no thread has been created to execute the task - If the thread pool is full, a reject policy is used to process tasks that cannot be executed
handler
Parameters related to
5. Executors Create and return to the ThreadPoolExecutor object
There are three methods for creating a return ThreadPoolExecutor object:
- Executors#newCachedThreadPool => create a cacheable thread pool
- Executors#newSingleThreadExecutor => Create a single-threaded thread pool
- Executors#newFixedThreadPool => Create a fixed-length thread pool
5.1 Executors# newCachedThreadPool method
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}Copy the code
CachedThreadPool
Is a thread pool that creates new threads as needed- CorePoolSize => 0, the number of core thread pools is 0
- MaximumPoolSize => integer. MAX_VALUE, the maximum number of thread pools is integer. MAX_VALUE
- keepAliveTime => 60L
- The unit = > seconds
- workQueue => SynchronousQueue
When a task is submitted, corePoolSize 0 does not create a core thread. SynchronousQueue is a queue that does not store elements and is understood to be always full, so a non-core thread is eventually created to execute the task. Non-core threads that are idle for 60 seconds will be reclaimed. ** Because integer. MAX_VALUE is very large, it can be assumed that threads can be created indefinitely, which can cause OOM exceptions if resources are limited
5.2 Executors# newSingleThreadExecutor method
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}Copy the code
SingleThreadExecutor is a single-threaded thread pool with only one core thread
- CorePoolSize => 1, the number of core thread pools is 1
- MaximumPoolSize => 1, the maximum number of thread pools is 1, that is, only one thread can be created, and the only thread is the core thread
- keepAliveTime => 0L
- The unit = > milliseconds
- workQueue => LinkedBlockingQueue
When a task is submitted, a core thread is first created to execute the task. If the number of core threads exceeds the number, the task will be queued. Because the LinkedBlockingQueue is an unbounded queue with length integer. MAX_VALUE, an infinite number of tasks can be inserted into the queue. It is easy to raise an OOM exception when resources are limited, maximumPoolSize and keepAliveTime parameters will not be valid because of unbounded queues, and non-core threads will not be created at all
5.3 Executors# newFixedThreadPool method
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}Copy the code
A FixedThreadPool is a pool of fixed core threads passed in by the user
- CorePoolSize => nThreads, the number of core thread pools is 1
- MaximumPoolSize => nThreads, the maximum number of threads in the pool is nThreads, that is, only nThreads can be created
- keepAliveTime => 0L
- The unit = > milliseconds
- WorkQueue > and LinkedBlockingQueue it
SingleThreadExecutor
Similarly, the only difference is that the number of core threads is different, and since ** usesLinkedBlockingQueue
Is easily caused when resources are limitedOOM
abnormal
Six, three ways to summarize
- FixedThreadPool and SingleThreadExecutor => allow the request queue length to be integer. MAX_VALUE, which may cause a large number of requests to pile up
OOM
abnormal - CachedThreadPool => The number of threads allowed to be created is integer. MAX_VALUE, which may cause a large number of threads to be created
OOM
abnormal
Seven, OOM abnormal test
public class TaskTest { public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); int i = 0; while (true) { es.submit(new Task(i++)); }}}Copy the code
Keep the JVM memory down before starting the test classes / / or you could Run your PC out of trouble. If you don’t follow the following steps, Run -> Edit Configurations
When creating multiple threads to 3W, an OOM error will be reported. The other two thread pools will not be tested. The test method is the same, but the thread pool created is different
How to define thread pool parameters
- cpu-intensive=> The recommended size of the thread pool is
CPU
Quantity plus 1,CPU
Quantity can be based onRuntime.availableProcessors
Methods to obtain - IO intensive= >
CPU
The number of *CPU
Utilization * (1 + thread wait time/thread CPU time) - A hybrid=> Divide tasks into two groups
CPU
Intensive andIO
Intensive, which is then handled separately by separate thread pools so that each thread pool can be tailored to its own workload - Blocking queue => You are advised to use a bounded queue to avoid resource exhaustion
- Rejection policies = > default is AbortPolicy refused to strategy, directly in the program throws RejectedExecutionException exception because be a runtime exception, don’t forced to catch 】, this way of handling enough grace. The rejection policies are recommended as follows:
- Capture in the program
RejectedExecutionException
Exception, the task is handled in catching an exception. For the default reject policy - use
CallerRunsPolicy
Reject policy, which assigns tasks to the thread that calls execute, in which case the main thread cannot commit any tasks for a period of time, allowing the worker thread to handle the tasks in progress. At this point the submitted thread will be saved inTCP
When the TCP queue is full, the client is affected, which is a gentle performance degradation - User-defined rejection policy, only need to implement
RejectedExecutionHandler
The interface can be - If the task is not particularly important, use
DiscardPolicy
andDiscardOldestPolicy
It is also possible to reject a policy to drop a task
- Capture in the program
If you use the Static method of Executors to create a ThreadPoolExecutor object, use Semaphore to limit traffic during task execution or avoid OOM exceptions
How to create a thread pool correctly
9.1 ScheduledExecutorService
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()
);
executorService.execute(() -> System.out.println("run"));Copy the code
9.2 new ThreadFactoryBuilder ()
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
ExecutorService executor = new ThreadPoolExecutor(
5, 200, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()
);
executor.submit(() -> System.out.println(Thread.currentThread().getName() + "run"));
executor.shutdown();Copy the code
9.3 ThreadPoolTaskExecutor XML Mode
Juejin. Cn/post / 684490…
My.oschina.net/u/4440046/b…
This article is published by OpenWrite, a blogging tool platform