What is a thread pool

A thread is the smallest unit in which an operating system can schedule operations. It is contained in the process, it is the actual operating unit of the process, and our programs are ultimately run by threads. In Java, the act of creating and destroying threads is resource-intensive, hence the so-called “pooling resource” technique. Thread pool is an application of the technology of pooling resources, the thread pool, just as its name implies is to press a regulation in advance to create a number of executable threads in a container (pool), you need to use the time to get from the thread pool, use after not destroyed but back, thereby reducing the number of threads created and destroyed, achieve the goal of saving resource.

2. Why use thread pools

2.1 Reduce resource consumption

As mentioned earlier, thread pools reduce the number of threads created and destroyed, and each thread can be reused to perform multiple tasks.

2.2 Improve system response speed

Reusing threads from the thread pool every time a task comes in, rather than waiting for a new thread to be created, improves response time

2.3 Prevent excessive threads from damaging the system

You can adjust the number of worker threads in the thread pool based on the system’s capacity to prevent a server from slowing down or crashing because of too many threads. The default Java thread footprint is 1M, so you can imagine that if you manually create too many lines, you will run out of memory.

3. Main parameters of the thread pool

You can use the Executors class to create thread pools, but ali does not allow you to create thread pools directly by following the Executors class.

ThreadPoolExecutor creates a thread pool by following the Executors class. If so, go back to the following classes: * If so, go back to the following classes: * If so, go back to the following classes: * If so, go back to the following classes:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)Copy the code




3.1 corePoolSize

When a task is submitted to a thread pool, if the number of threads created in the thread pool is smaller than corePoolSIze, a new thread is created to execute the task, even if there are idle threads, until the number of threads created is greater than or equal to corePoolSIze.

3.2 maximumPoolSize

The maximum number of threads allowed by the thread pool. When the queue is full and the number of threads created is smaller than maximumPoolSize, a new thread is created to execute the task.

3.3 keepAliveTime

When the number of threads in a thread is greater than corePoolSIze, the thread is destroyed if its idle time is greater than keepAliveTime.

3.4 the unit

KeepAliveTime Unit of keepAliveTime

3.5 workQueue

Used to hold queues for tasks to be executed

3.6 threadFactory

Used to create a new thread. ThreadFactory creates threads that use new Thread(). ThreadFactory creates Thread names that have the same style: pool-m-thread-n

3.7 handler

Reject policy, which is implemented when new threads are added to the thread pool and queue after the pool and queue are full.

Here are four thread pool rejection policies:

AbortPolicy: Interrupts the task and throws an exception

DiscardPolicy: Mid-course task without throwing an exception

DiscardOldestPolicy: Discards the oldest task in the queue and tries to submit a new task

CallerRunsPolicy: This task is handled by the calling thread

4. Thread pools execute processes

Once we understand the seven parameters of ThreadPoolExecutor, we can quickly understand the flow of thread pools:



When submitting, first of all, judge whether the current thread count more than the core number of threads, if not more than create a new thread to perform a task, or whether the work queue is full, if not add tasks to the queue, or whether the number of threads more than the maximum number of threads, if not, create a thread executed task, otherwise refuse strategy execution.

5. Thread pool provided by Executors

Executors provide many kinds of thread pools for users to use. While many companies prohibit building thread pools by using Executors, the thread pools provided by Executors are a great way to get into the world of threads for starters.

5.1 newSingleThreadExecutor

ExecutorService executorService = Executors.newSingleThreadExecutor();Copy the code

CorePoolSize is 1, maximumPoolSize is 1, corePoolSize is 1, maximumPoolSize is 1, corePoolSize is 1.

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue()));
}Copy the code

5.2 newFixedThreadPool

ExecutorService executorService = Executors.newFixedThreadPool(2);Copy the code

A fixed-length thread pool whose length is passed in by a variable when it is created. Here is the constructor of newFixedThreadPool, corePoolSize and maximumPoolSize being passed in as parameter values

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue());
}Copy the code

5.3 newCachedThreadPool

ExecutorService executorService = Executors.newCachedThreadPool();Copy the code

Cacheable thread pool, which sets keepAliveTime to 60 seconds and has little control over the maximum number of threads.

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue());
}Copy the code

Look at the constructors, corePoolSize = 0, maximumPoolSize = integer.max_value, that is, the number of threads is almost unlimited. KeepAliveTime is set to 60 seconds, and the thread automatically terminates after 60 seconds. Because this thread pool is created indefinitely and no queue is waiting, SynchronousQueue is used to synchronize the queue.

5.4 newScheduledThreadPool

Create a timed thread pool. This thread pool supports the need to execute tasks regularly and periodically. Here is how newScheduledThreadPool is used:

Thread thread1=new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread1"); }}); Thread thread2=new Thread(newRunnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread2"); }}); Thread thread3=new Thread(newRunnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread3"); }}); ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); / / in 1000 ms after execution thread1 scheduledExecutorService. The schedule (thread1, 1000, TimeUnit. MILLISECONDS); Thread2 is executed every 1000ms after 1000ms. If the task execution time is longer than the interval, Will delay the scheduledExecutorService. ScheduleAtFixedRate (thread2, 1000100, TimeUnit. MILLISECONDS); // It is similar to the second method, but the next task starts at: The last task over time (rather than the beginning of time) + delay time scheduledExecutorService. ScheduleWithFixedDelay (thread3, 1000100, TimeUnit. MILLISECONDS);Copy the code

6. Why does Alibaba forbid programmers from using Exectors to create thread pools

If your idea is loaded with Alibaba Java Codeing Guidelines (recommended to make your code more standardized), you will see a message when you write Exectors to create a thread pool:



Ali also defines this use as Blocker, which is not allowed and instead lets people create thread pools as ThreadPoolExecutor. The reason for this is that, with ThreadPoolExecutor, the writer is more aware of the thread pool rules and avoids the risk of running out of resources.



* If the thread pool object returns by Executors, it has the following disadvantages:

1) FixedThreadPool and SingleThreadPool

The allowed queue length is integer. MAX_VALUE, which may accumulate a large number of requests and result in OOM.

2) CachedThreadPool:

The number of threads allowed to be created is integer.max_value, which may create a large number of threads, resulting in OOM.

Here is a simple example of ThreadPoolExecutor creating a thread pool

int corePoolSize=5;
int maximumPoolSize=10;
long keepAliveTime=30;
BlockingQueue blockingQueue=new ArrayBlockingQueue(2);
RejectedExecutionHandler handler=new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, blockingQueue, handler);
threadPoolExecutor.execute(thread1);Copy the code

7. To summarize

If you have any questions, questions or additions to this article, please leave a comment or send me a private message. Welcome to follow my wechat public account “Fishy LY” to communicate with me, and make progress a little bit every day.