Thread Pool Series No More Threaded Thread Pools

Keywords: Java Database github Programming

background

Origin of thread pool

Server-side programs, such as database servers and Web servers, create a thread to process requests from clients each time they receive them.

Threads can be created in many ways, such as inheriting the Thread class, implementing the Runnable or Callable interface, and so on.

This seemingly easy way to process client requests by creating new threads has a large drawback and high risk.

As the saying goes, the simpler the way, the more difficult the way, the simpler the way is.

Creating and destroying threads consumes a lot of server resources, even longer than the thread itself takes to process tasks.

Since starting threads consumes a lot of server resources, it is necessary to limit the number of threads created if too many threads are created, which can cause the system to run out of memory.

What is a thread pool

Thread pools are typically a pool to take out and put back threads that were created earlier, conceptually similar to a database connection pool.

So how does a thread pool work?

In fact, thread pools are designed to significantly reduce resource consumption caused by frequent thread creation and destruction by creating threads to handle current tasks prior to reuse.

A thread pool reuses previously created threads to execute current tasks and offers a solution to the problem of thread cycle overhead and resource thrashing. Since the thread is already existing when the request arrives, the delay introduced by thread creation is eliminated, making the application more responsive.

Background Summary

Here's a summary of some of the first introductions to thread pools.

  1. Threads are part of programs that help us do things.
  2. Multiple threads can help us do things at the same time, which can greatly improve the efficiency of our work by maximizing the use of server resources.
  3. Every thread we create is not a fuel-efficient lamp. The more threads we have, the more system resources we will occupy. So don't be greedy, although younger brother is good. Threads are not "Korean letter soldier, more beneficial", but limit the number of threads.Keep this in mind, because this is the "culprit" when the thread pool provided by Java below creates a solution.
  4. Creating and destroying threads can take a lot of system resources, just like big boys recruiting and dismissing young brothers.So smart guys think of "pools", caching threads and putting them back when they are used and taken out when they are not used. This allows you to enjoy multi-threaded fun and avoid the pain of using multi-threaded.

But how do you actually use thread pools?Is thread pooling really that easy to use?Are there any pits in the process of using the thread pool?

Don't worry, let's take a look at some of the different ThreadPool postures, what's cool and what's painful.

Prepare paper towels, cough... it's a notebook, Tao Ge wants to tell you!

usage

Create a thread pool from Executors

Executors and classes of their services

java.util.concurrent.Executors is a factory class and a tool class provided under the concurrent package of JDK.

Executors provides factory methods and tool methods related to Executor, Executor Service, Scheduled Executor Service, ThreadFactory, and Callable.

Executor is an object that performs a submission of Runnable Tasks and has an execute method with a Runnable parameter.When the execute method is executed, tasks in parameters are executed at a future time by creating a thread or by using threads in the thread pool.The usage is as follows:

Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());

ExecutorService inherits Executor and provides more interesting methods, such as shutdown, that will make ExecutorService refuse to create new threads to execute task s.

Several methods commonly used by Executors


//Create a thread pool with a fixed number of threads
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);

//Create a thread pool that creates new threads as needed, but reuses previously created threads if they are available
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

//Create a thread pool with only one thread
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

An example of a thread pool

Next, I'll create five Tasks and execute the Task through a thread pool with three threads.Let's see what happens together.

Github full code: an example of a thread pool

ThreadPoolExample1 is our test class, and all the internal classes, constants, and methods below are written in this test class.

package net.ijiangtao.tech.concurrent.jsd.threadpool;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample1 {

}

task

The Task internal class executes two for loops and sleep for one second after the end of each loop.

// Task class to be executed (Step 1)
static class Task implements Runnable {

    private String name;

    public Task(String s) {
        name = s;
    }

    // Prints task name and sleeps for 1s
    // This Whole process is repeated 2 times
    public void run() {
        try {
            for (int i = 0; i <= 1; i++) {
                if (i == 0) {
                    //prints the initialization time for every task
                    printTimeMsg("Initialization");
                } else {
                    // prints the execution time for every task
                    printTimeMsg("Executing");
                }
                Thread.sleep(1000);
            }
            System.out.println(name + " complete");
        } catch (InterruptedException e) {
                e.printStackTrace();
        }
    }

    private void printTimeMsg(String state) {
        Date d = new Date();
        SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
        System.out.println(state+" Time for"+ " task name - " + name + " = " + ft.format(d));
    }
}

Pond

Create a thread pool with a fixed number of threads.

// Maximum number of threads in thread pool
static final int MAX_T = 3;
// creates a thread pool with MAX_T no. of
// threads as the fixed pool size(Step 2)
private static final ExecutorService pool = Executors.newFixedThreadPool(MAX_T);

test

Create five tasks and execute them through threads in the thread pool.

public static void main(String[] args) {
     // creates five tasks
     Runnable r1 = new Task("task 1");
     Runnable r2 = new Task("task 2");
     Runnable r3 = new Task("task 3");
     Runnable r4 = new Task("task 4");
     Runnable r5 = new Task("task 5");

     // passes the Task objects to the pool to execute (Step 3)
     pool.execute(r1);
     pool.execute(r2);
     pool.execute(r3);
     pool.execute(r4);
     pool.execute(r5);

     // pool shutdown ( Step 4)
     pool.shutdown();
}

The results are as follows.

Initialization Time for task name - task 1 = 12:39:44
Initialization Time for task name - task 2 = 12:39:44
Initialization Time for task name - task 3 = 12:39:44
Executing Time for task name - task 3 = 12:39:45
Executing Time for task name - task 1 = 12:39:45
Executing Time for task name - task 2 = 12:39:45
task 2 complete
Initialization Time for task name - task 4 = 12:39:46
task 3 complete
Initialization Time for task name - task 5 = 12:39:46
task 1 complete
Executing Time for task name - task 5 = 12:39:47
Executing Time for task name - task 4 = 12:39:47
task 5 complete
task 4 complete

Explain

From the output, we can see that five tasks are executed in a thread pool with three threads.

  1. First, three tasks (task 1, task 2, task 3) get the thread resources and execute concurrently.
  2. (task 2) After successful execution, give up thread resources and (task 4) start execution;
  3. (task 3) After successful execution, give up thread resources and (task 5) start execution;
  4. Finally, all five tasks end and the thread pool recycles thread resources.

Because the execution of threads is random and the resources of different machines are different, the results of each execution may vary.

Here is the result of my second execution.

Initialization Time for task name - task 1 = 12:46:33
Initialization Time for task name - task 3 = 12:46:33
Initialization Time for task name - task 2 = 12:46:33
Executing Time for task name - task 2 = 12:46:34
Executing Time for task name - task 3 = 12:46:34
Executing Time for task name - task 1 = 12:46:34
task 3 complete
task 2 complete
task 1 complete
Initialization Time for task name - task 4 = 12:46:35
Initialization Time for task name - task 5 = 12:46:35
Executing Time for task name - task 4 = 12:46:36
Executing Time for task name - task 5 = 12:46:36
task 5 complete
task 4 complete

task 1 2 3 gets thread resources, task 4 5 queues:

The task 1 2 3 execution ends, task 4 5 gets the thread resources, and one thread in the thread pool is idle:

However, the rule is the same: a thread pool contributes its own thread resources, and if the number of tasks exceeds the number of threads in the thread pool, it blocks and queues for available thread resources to execute later.

That is, the thread pool guarantees that your task will be executed at some point in the future, but it does not guarantee when it will be executed.

You now have a better understanding of the invokeAll method of ExecutorService by executing a batch of task s and returning a Future collection.

List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException

The process of executing a task through the ExecutorService thread pool is illustrated below. Taks that exceed the number of thread pool threads will be queued in BlockingQueue for an opportunity to obtain thread resources.

I have an article about Futrue in concurrent programming ( Java Concurrent Programming - Introduction and Basic Usage of Future Series ) Specifically, please step through any of the links below to enjoy:

summary

This tutorial takes you through the origin, concepts and basic usage of thread pools, and I believe that once you have read them, you will no longer be foolishly new Thread.

This section is just the beginning of a thread pool. Here are more tips on how to do martial arts with a thread pool. I hope you will keep your eyes on it and benefit from it.

Like to have your favorite forwards, if you're interested in this series, I'll keep updating.
👍

Links

Article Friend Chain

Related Resources

Concurrent-ThreadPool-Thread Pool Rejection Policy RejectedExecutionHandler

Four rejection policies in Concurrent-ThreadPool-ThreadPoolExecutor

Concurrent-ThreadPool-ThreadPool ThreadPoolExecutor construction methods and rules

Concurrent-ThreadPool-The Way to Thread Pool Growth

Similarities and differences between Concurrent-ThreadPool-LinkedBlockingQueue and Array BlockingQueue

Concurrent-ThreadPool-Summary of optimal number of threads

Concurrent-ThreadPool-Optimal number of threads

Concurrent-ThreadPool-Thread Pools in Java

Concurrent-ThreadPool-java-thread-pool

Concurrent-ThreadPool-thread-pool-java-and-guava

Concurrent-ThreadPool-ijiangtao.net

Posted by bernouli on Sat, 11 May 2019 13:48:35 -0700