The concept of threads

thread

The JVM uses KLT. The JVM uses KLT. Java threads have a 1:1 mapping between OS threads and Java threads. Java threads have multiple lifestates

// Enumeration of thread states
public enum State {
  NEW, // create, call start()

  RUNNABLE, / / ready

  BLOCKED, // Block, contention does not get lock

  WAITING, / / wait for

  TIMED_WAITING, // Wait for timeout

  TERMINATED; / / termination
}
Copy the code

coroutines

The Java designers also failed to provide developers with API support for coroutines. Therefore, if we want to use coroutines in our programs to improve the performance of our applications in certain scenarios, we have to rely on third-party open source artifacts (e.g. Quasar, Coroutines, Kilim, etc.) or hybrid programming (e.g. Kotlin).

Java thread pool

Thread Pool is a tool to manage threads based on pooling idea, which often appears in multi-threaded server, such as MySQL.

Too many lines will bring extra costs, including the cost of creating and destroying threads, the cost of scheduling threads, etc., and also reduce the overall performance of the computer. A thread pool maintains multiple threads waiting for a supervisor to assign tasks that can be executed concurrently. This approach, on the one hand, avoids the cost of creating and destroying threads while processing tasks, on the other hand, avoids the excessive scheduling problem caused by the expansion of the number of threads, and ensures the full utilization of the kernel.

Advantages of thread pools

There are three benefits to using thread pools properly:

  1. Reduce resource consumption. Reduce the cost of thread creation and destruction by reusing created threads.
  2. Improve response speed. When a task arrives, it can be executed immediately without waiting for the thread to be created.
  3. Improve thread manageability. Threads are scarce resources. If created without limit, they consume system resources and degrade system stability. Thread pools can be used for uniform allocation, tuning, and monitoring. However, to make good use of thread pools, you must have a thorough understanding of how they are implemented.

Create a parameter

We can create a thread pool using ThreadPoolExecutor. It is constructed as follows:

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
   milliseconds,runnableTaskQueue, handler);
Copy the code

To create a thread pool, enter the following parameters:

CorePoolSize (base size of thread pool) : When a task is submitted to the thread pool, the thread pool creates a thread to execute the task, even if other free base threads are able to execute the new task. The thread is not created until the number of tasks to execute exceeds the base size of the thread pool. If the thread pool’s prestartAllCoreThreads() method is called, the pool creates and starts all base threads ahead of time.

RunnableTaskQueue: A blocking queue that holds tasks waiting to be executed. You can choose from the following blocking queues.

  1. ArrayBlockingQueue: ArrayBlockingQueue is a bounded blocking queue based on an array structure that sorts elements in A FIFO(first-in, first-out) order.
  2. LinkedBlockingQueue: A LinkedBlockingQueue based on a linked list structure that sorts elements in FIFO and has a higher throughput than ArrayBlockingQueue. Static factory methods Executors. NewFixedThreadPool () using the queue
  3. SynchronousQueue: A blocking queue that does not store elements. Each insert operation must wait until another thread calls to remove operation, otherwise the insert has been in the blocking state, the throughput is usually more than the Linked – BlockingQueue, static factory methods Executors. NewCachedThreadPool using the queue.
  4. PriorityBlockingQueue: An infinite blocking queue with a priority.

MaximumPoolSize: The maximum number of threads allowed to be created in a thread pool. If the queue is full and the number of created threads is less than the maximum, the thread pool creates a new thread to execute the task. It is worth noting that this parameter has no effect if an unbounded task queue is used.

ThreadFactory: Used to set up a factory for creating threads. You can use the ThreadFactory to give each created thread a meaningful name. You can quickly set meaningful names for threads in a thread pool using ThreadFactoryBuilder provided by the open source framework Guava. new ThreadFactoryBuilder().setNameFormat(“XX-task-%d”).build();

RejectedExecutionHandler(saturation policy): When both the queue and the thread pool are full, the thread pool is saturated and a policy must be adopted to handle submitted new tasks. This policy is AbortPolicy by default, indicating that an exception is thrown when a new task cannot be processed. The Java thread pool framework provides the following four strategies in JDK 1.5.

  1. AbortPolicy: Directly throws an exception.
  2. CallerRunsPolicy: Run the task only in the caller’s thread.
  3. DiscardOldestPolicy: Discards the most recent task in the queue and executes the current task.
  4. DiscardPolicy: Do not process, discard.

You can also customize the RejectedExecutionHandler interface based on application scenarios. Tasks that cannot be handled by logging or persistent storage.

KeepAliveTime: The amount of time that a worker thread in a thread pool stays alive after it is idle. Therefore, if there are many tasks and the execution time of each task is short, you can adjust the time to improve thread utilization.

TimeUnit(a unit of hold time for thread activity): The options are in DAYS, HOURS, MINUTES, MILLISECONDS, MICROSECONDS and NANOSECONDS.

The working principle of

Through the description of the above parameters, we have a general understanding of how to initialize a thread pool. The submission and execution of thread pool tasks are shown in the following figure:

Code sample

Here is a simple example of creating a thread pool and call for your reference:

// Create a thread pool
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolTest {

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2.4.0, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10),
                new ThreadFactory() {
                    int i = 0;

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName("pool-test-" + i++);
                        returnthread; }},// CallerRunsPolicy if the current thread pool is not closed, the thread of the current submitted task will be called to participate in the execution
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        for (int i = 0; i < 100; i++) {
            threadPool.submit(new Runnable() {
                @Override
                public void run(a) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    String name = Thread.currentThread().getName();
                    if ("main".equals(name)) {
                        // CallerRunsPolicy Policy submission task thread participates in the execution
                        System.out.println("this is a idea debug line");
                    }
                    System.out.println(name + ":" + this.toString()); }}); } threadPool.shutdown();while (true) {
            if (threadPool.isTerminated()) {
                System.out.println("All child threads are finished!");
                break;
            }
            Thread.sleep(100); }}}Copy the code

Reference for setting thread number

  1. CPU intensive: number of CPU cores + 1
  2. IO intensive: twice the number of CPU cores + 1

The resources

  • Infoq takes a deep look at Java coroutines
  • Implementation principle of Java thread pool and its practice in Meituan business