This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

preface

Most of us are confused about the thread pool execution flow, and the relationship between the number of core threads and the maximum number of threads is not clear.

A lot of times we don’t know whose thread we’re talking about. This article highlights what we call the differences and connections between Java threads and operating system threads.

Java thread

Java threads are divided into six states, and here is a clear picture of the flow between the states.

Only in the Runnable state is the CPU actually executed.

The diagram also identifies the flow conditions between different states. During debugging, thread.getState () may be used to print the current Thread state.

I won’t go into details about each specific flow process here, you see the picture, at a glance.

It is important to note that in a waiting state to a runnable state, if the thread can acquire the lock, it is normally promoted to runnable, otherwise it is blocked.

Operating system level threads

There are five operating system level thread states: New, ready, running, blocked, and terminated. The corresponding Java thread state here has a correspondence as shown in the figure.

I have to make a joke here. Many articles confuse these states and use a single graph, which is a description of threads at a different level.

The scenarios for thread blocking at the operating system level include blocking IO, blocked, waiting, and timed waiting.

The runnable Java might correspond to the operating system of the ready | | blocking IO.

Create threads in Java

The first is to inherit the Thread class and implement the run method. The second is to implement the Runnable interface and implement the run method. Note that the run method is only the business logic that the Thread needs to execute. To actually start the Thread, our main function calls the Thread start method, which puts the Thread into the new state mentioned above.

However, when we do use multithreading, we rarely create a single thread, and most of the time consider using a thread pool.

The thread pool

One of ali’s development specifications explicitly states that threads must be obtained from the thread pool in order to use them. Why?

The benefit of using thread pools is to reduce the time spent creating and destroying threads and the overhead of system resources, solving the problem of insufficient resources. If you do not use a thread pool, you can run out of memory or “overswitch” threads by creating a large number of similar threads.

The main class we use for thread pools is ThreadPoolExecutor, and no matter how we call it, we end up with a constructor. Let’s analyze what each parameter means.

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
Copy the code

CorePoolSize: number of core threads, maximum number of retained threads.

MaximumPoolSize: the maximum number of threads, the number of core threads + the number of emergency threads

KeepAliveTime: Indicates the duration of the emergency thread

Unit: Time unit for emergency threads

WorkQueue: blocking queue

ThreadFactory: a threadFactory that gives a thread a good name when it is created

Handler: refuse strategy, a total of four, respectively is discarded thrown exception first mission | | | abandoned discard team by the caller to handle the Task

ThreadPoolExecutor runs the process

First, the core thread executes tasks, more tasks are added to the workQueue, and when the workQueue is full, the emergency thread is called up to execute tasks from the workQueue. When no new tasks are added to the workQueue during keepAliveTime, the emergency thread is released from the thread pool. If the emergency thread runs out and a new task arrives, it will react according to handler rejection policy.

It is important to note that this does not mean that the core thread is used up and then immediately on the emergency thread!! The workQueue must be of a specified length or it may run out of memory

conclusion

That’s all the content of this article, mainly talking about the differences between different layers of threads, as well as the definition and use of threads in Java, thread pool running process and considerations.

Unless multithreading is not available, use thread pools, and unless not use thread pools, you need to set the length of the blocking queue.