Solve all the questions of the Java thread pool interview in five minutes

1. Why use thread pool

  1. Reduce resource consumption. Reduce the consumption caused by thread creation and destruction by reusing the created threads.

  2. Improve response speed. When the task arrives, the task can be executed immediately without waiting for the thread to be created.

  3. Improve the manageability of threads. Thread is a scarce resource. If created unlimitedly, it will not only consume system resources, but also reduce the stability of the system. The thread pool can be used for unified allocation, tuning and monitoring.

2. Detailed explanation of seven parameters of ThreadPoolExecutor thread pool class

parameter Description
corePoolSize The number of core threads, the minimum number of threads that the thread pool maintains
maximumPoolSize The maximum number of threads maintained by the thread pool
keepAliveTime The longest idle time of threads other than the core thread in the thread pool, and idle threads that exceed this time will be destroyed
unit The unit of keepAliveTime, several static attributes in TimeUnit: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS
workQueue Task buffer queue used by thread pool
threadFactory Thread factory, used to create threads, generally use the default
handler Thread pool's processing strategy for rejected tasks

When the thread pool task cannot be processed, it can be processed through the strategy specified by the handler.

ThreadPoolExecutor provides four strategies:

  1. ThreadPoolExecutor.AbortPolicy: Abandon the task and throw RejectedExecutionException ; it is also the default processing method.
  2. ThreadPoolExecutor.DiscardPolicy: Discard the task without throwing an exception .
  3. ThreadPoolExecutor.DiscardOldestPolicy: Discard the first task in the queue, and then try to execute the task again (repeat this process)
  4. ThreadPoolExecutor.CallerRunsPolicy: the task is handled by the calling thread

The processing method can be customized by implementing the RejectedExecutionHandler interface.

Three, thread pool task execution

1. Add an execution task

  • submit() This method returns a Future object, which can execute a thread with a return value; or execute a thread that you want to cancel at any time. The get() method of the Future object gets the return value. The cancel (true/false) of the Future object cancels the task, returns false if it is not started or has been completed, and the parameter indicates whether to interrupt the executing thread
  • execute() has no return value.

2. Thread pool task submission process

2.1. If the number of thread pools is less than corePoolSize at this time, even if the threads in the thread pool are idle, new threads must be created to handle the added tasks.
2.2. If the number of thread pools is equal to corePoolSize at this time, but the buffer queue workQueue is not full , then the task is put into the buffer queue.
2.3. If the number in the thread pool is greater than or equal to corePoolSize, the buffer queue workQueue is full, and the number in the thread pool is less than the maximumPoolSize, a new thread is created to process the added tasks.
2.4. If the number in the thread pool is greater than corePoolSize, the buffer queue workQueue is full, and the number in the thread pool is equal to the maximumPoolSize, then the task is processed by the strategy specified by the handler .
2.5. When the number of threads in the thread pool is greater than corePoolSize, if a thread's idle time exceeds keepAliveTime, the thread will be terminated. In this way, the thread pool can dynamically adjust the number of threads in the pool.

The summary is: the priority of processing task judgment is the core thread corePoolSize, task queue workQueue, and maximum thread maximumPoolSize. If all three are full, use the handler to process the rejected task.

note:

  1. When the workQueue uses the ××× limit queue, the maximumPoolSize parameter becomes meaningless, such as new LinkedBlockingQueue(), or new ArrayBlockingQueue(Integer.MAX_VALUE);
  2. When using the SynchronousQueue queue, because the queue has no capacity, the task will not be queued. If there is no idle thread in the thread pool, a new thread will be created immediately to receive the task. The maximumPoolSize should be set larger.
  3. KeepAliveTime has no effect when the number of core threads and maximum threads are equal.

3. Thread pool is closed

3.1. shutdown() does not accept new tasks and will process added tasks
3.2. shutdownNow() does not accept new tasks, does not process added tasks, and interrupts tasks that are being processed

4. Introduction to Common Queues

4.1. ArrayBlockingQueue: This is a bounded blocking queue with a fixed capacity implemented by an array .
4.2. SynchronousQueue: Without capacity, data cannot be cached; each put must wait for a take; if there is no other thread in poll at the time of offer() () or take() will return false.
4.3. LinkedBlockingQueue: This is a default ××× blocking queue implemented by a singly linked list. LinkedBlockingQueue provides an optional bounded constructor, and when the capacity is not specified, the capacity defaults to Integer.MAX_VALUE .

Queue operation:

method Description
add Add a yuansoil; if the queue is full, throw an exception
remove Remove and return the element at the head of the queue; if the queue is empty, an exception is thrown
offer Add an element and return true; if the queue is full, return false
poll Remove and return the element at the head of the queue; if the queue is empty, return null
put Add an element; if the queue is full, block
take Remove and return the element at the head of the queue; if the queue is empty, block
element Returns the element at the head of the queue; if the queue is empty, an exception is thrown
peek Return the element at the head of the queue; if the queue is empty, return null

5. Executors thread factory class

1. Executors.newCachedThreadPool();
Description: Create a cacheable thread pool. If the length of the thread pool exceeds the processing requirement, idle threads can be recycled flexibly. If there is no recycling, new threads can be created.
Internal implementation: new ThreadPoolExecutor(0,Integer. MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<runnable>());</runnable>

2. Executors.newFixedThreadPool(int);
Description: Create a fixed-length thread pool, which can control the maximum concurrent number of threads, and the excess threads will wait in the queue.
Internal implementation: new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>());</runnable>

3. Executors.newSingleThreadExecutor();
Description: Create a single-threaded thread pool, it will only use a single worker thread to perform tasks, ensuring that all tasks are executed in order.
Internal implementation: new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>())</runnable>

4. Executors.newScheduledThreadPool(int);
Description: Create a fixed-length thread pool to support timing and periodic task execution.
Internal implementation: new ScheduledThreadPoolExecutor(corePoolSize)

[Attached] Alibaba Java Development Manual for the use of thread pool specifications

  1. [Mandatory] When creating a thread or thread pool, please specify a meaningful thread name to facilitate backtracking in case of errors.
    Positive example:

    public class TimerTaskThread extends Thread {
    public TimerTaskThread(){
        super.setName("TimerTaskThread"); 
        ...
    }
    }
  2. [Mandatory] Thread resources must be provided through the thread pool, and it is not allowed to explicitly create threads in the application.
    Note: The advantage of using the thread pool is to reduce the time spent on creating and destroying threads and the overhead of system resources, and to solve
    the problem of insufficient resources . If the thread pool is not used, it may cause the system to create a large number of threads of the same type and cause
    the problem of running out of memory or "over switching".

  3. [Mandatory] Thread pools are not allowed to be created using Executors, but are created by ThreadPoolExecutor. This way
    of processing allows students to write more clearly the operating rules of the thread pool and avoid the risk of resource exhaustion.

Explanation: The drawbacks of the thread pool objects returned by Executors are as follows:
1) FixedThreadPool and SingleThreadPool: The
allowed request queue length is Integer.MAX_VALUE, which may accumulate a large number of requests, which may lead to OOM.
2) CachedThreadPool and ScheduledThreadPool: The
allowed number of threads to be created is Integer.MAX_VALUE, which may create a large number of threads, leading to OOM.

6. Summary

ThreadPoolExecutor defines different types of thread pools through several core parameters, which are suitable for different usage scenarios; among them, when a task is submitted, it will determine corePoolSize, workQueque, and maximumPoolSize in sequence, and different states are processed differently.

Configuration basis of core parameters

1.1, the number of core threads corePoolSize

The design of the number of core threads needs to be determined according to the processing time of the task and the number of tasks generated per second. For example, it takes 0.1 seconds to execute a task, and the system generates 100 tasks per second in 80% of the time. Then we want to To process these 100 tasks in 1 second, 10 threads are required. At this time, we can design the number of core threads to be 10. The actual situation at the time was impossible to be so average, so generally we can design according to the 2080 principle, that is, according to the percentage In the case of 80, the number of core threads is designed, and the remaining 20% ​​can be processed with the maximum number of threads.

1.2, the length of the task queue (workQueue)

The task queue length is generally designed as the number of core threads/execution time of a single task*2 (maximum waiting time of the task/s). For example, in the above scenario, the number of core threads is designed to be 10, and the execution time of a single task is 0.1, so the queue length can be Designed to 200

1.3, the maximum number of threads (maximumPoolSize)

The design of the maximum number of threads not only needs to refer to the condition of the number of core threads, but also needs to refer to the maximum number of tasks generated by the system per second. For example, in the above environment, if the maximum number of tasks generated by the system per second is 1000, then the maximum thread Number = (maximum number of tasks-task queue length) * the execution time of a single task; both the maximum number of threads = (1000-200) * 0.1 = 80; of course, the maximum number of threads also has a lot to do with the hardware configuration of the server

 

Guess you like

Origin blog.csdn.net/qq_27828675/article/details/115357347