This is the second day of my participation in Gwen Challenge

Joke? You think I don’t have a girlfriend because I don’t understand thread pools

Concepts and Functions

Thread pools are the most widely used concurrency framework in Java, and can be used by almost any program that needs to perform tasks asynchronously or concurrently. There are three benefits to using thread pools properly during development.

  • Reduce resource consumption. Reduce the cost of thread creation and destruction by reusing created threads
  • Improve response speed. When a task arrives, it can be executed immediately without waiting for the thread to be created
  • Improve objective rationality of threads. 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

“The Art of Concurrent Programming in Java”

Realize the principle of

Let’s review the thread state

  • New — New (thread created and not started)
    • Inheriting Thread (calling the start method)
    • Implement the Runnable interface (call the run method)
    • Implement Callable interface (call method)
    • Thread pool ()
  • Runnable — Ready (state before running after calling start())
  • Running — Running (The state of a thread while run() is being executed, which may quit running due to factors such as timing, exceptions, locks, scheduling, etc.)
  • Blocked — blocked
    • Synchronous blocking – The lock is held by another thread
    • Active blocking — Calls to some of the Thread’s methods, such as sleep(), join(), and so on, to actively relinquish CPU execution rights
    • Wait to block — wait() is executed
  • Dead — Terminates (Terminates after the run is completed or the run exits due to an exception. This state is irreversible

Explore the thread pool parameters again

  • CorePoolSize – Number of resident core threads that remain in the pool even when idle, unless allowCoreThreadTimeOut is set
  • MaximumPoolSize – Maximum number of threads allowed in the pool. Must be greater than or equal to 1, if equal to corePoolSize that’s a fixed size thread pool. Once the queue cache is maxed out, the thread pool creates new threads if there are new tasks to be processed.
  • KeepAliveTime – Indicates the idle time of a thread in the thread pool. When the idle time reaches this value, the thread is destroyed until there are only corePoolSize threads left to avoid wasting memory and handle resources
  • Unit-keepalivetime Time unit of the keepAliveTime parameter
  • WorkQueue – Queues used before a task is executed. This queue will only hold Runnable tasks submitted by the execute method. When the number of requesting threads exceeds the number of core threads, the thread enters the BlockingQueue BlockingQueue. It is recommended to use bounded queue, which can increase the stability and warning ability of the system
  • ThreadFactory – Used to set up a factory for creating threads. You can give each created thread a meaningful name using the threadFactory
  • Handler-saturation policy, the handler used when execution is blocked because thread limits and queue capacity are reached, is also a simple flow limiting protection
    • AbortPolicy: Throws an exception directly (default)
    • CallerRunsPolicy: Run the task only in the caller’s thread
    • DiscardOldestPolicy: Discards the most recent task in the queue and executes the current task
    • DiscardPolicy: Do not process, discard
    • Custom policies: There are three friendly rejection policies: Save them to the database for peak load cutting and valley filling, and then extract them for execution in idle time; To a prompt page; Print log

Take a look at the process mechanism

They say a picture is better than a forewordThis is a very classic thread pool execution flow chart, but may be the first time to see some abstract, let the primary school brother to process it

Finally, the understanding of the weak chicken farmers

If you don’t understand, then you don’t deserve to be a loyal LPL viewer. No, no, then you don’t deserve to be a solid programmer

The sample code

Sorry for taking so long without a little code, everybody. Here we go. Serve

The main task

public class Task implements Runnable{

    private final static AtomicLong a = new AtomicLong(1L);

    @Override
    public void run(a) {
        // Sleep for three seconds and pretend to perform the "change of clothes" task
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("My uniform is changed. I'm Summoner Num_."+a.getAndIncrement()); }}Copy the code

Thread factory

public class UserThreadFactory implements ThreadFactory {

    private final String namePrefix;
    private final AtomicInteger nextId = new AtomicInteger();

    public UserThreadFactory(String whatFeatureOfGroup) {
        namePrefix = "UserThreadFactory's-" + whatFeatureOfGroup + "-Worker-";
    }

    @Override
    public Thread newThread(Runnable task) {
        String name = namePrefix + nextId.getAndIncrement();
        Thread thread = new Thread(null,task,name,0);
        System.out.println(thread.getName());
        returnthread; }}Copy the code

User-defined rejection policy

public class UserThreadHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println("I was rejected :"+executor.getActiveCount()+executor.getCompletedTaskCount() +executor.getCorePoolSize()+executor.getQueue()); }}Copy the code

Thread pool main method

public class ThreadPoolTest {
    public static void main(String[] args) {
        // Initialize the queue
        BlockingQueue blockingDeque = new LinkedBlockingQueue(3);
        // Create a factory object
        UserThreadFactory userThreadFactory = new UserThreadFactory("Team FPX locker room");
        // Create a rejection policy
        UserThreadHandler userThreadHandler = new UserThreadHandler();
        // Build a thread pool
        ThreadPoolExecutor tpe1 = new ThreadPoolExecutor(
                1.2.20,TimeUnit.SECONDS,blockingDeque,userThreadFactory,userThreadHandler);
        // Declare the task object
        Task task = new Task();
        // The thread pool becomes active
        for (int i = 1; i <= 6; i++) {
            tpe1.execute(task);
        }
        // Close the thread pool when it runs out, otherwise it will hog resources forevertpe1.shutdown(); }}Copy the code

Main method execution effect

The overall process just corresponds to the implementation process of the above primary school younger brother, all understand

The book says to be careful when using it

  • Set the appropriate number of working threads based on the actual service scenario
  • Thread resources must be provided through thread pools, and explicit thread creation is not allowed in the application
  • When creating a thread or thread pool, specify a meaningful thread name to facilitate backtracking

Finally, how do you properly configure thread pool parameters

And the book says, look at it in terms of task characteristics

  • Properties:
    • CPU intensive: The smallest configuration thread possible, such as a thread pool of “N+1” threads
    • IO intensive: As many configuration threads as possible, such as “2 x N” threads
    • Mixed task: If the execution time of two tasks is not very different, it can be split into two tasks. If the execution time of two tasks is too different, it does not need to be split
  • Priority: High, medium, low (consider PriorityBlockingQueue, which allows tasks with higher priority to be executed first)
  • Execution time: long, medium, short
  • Dependencies: Whether they depend on other system resources, such as database connections

Further optimization theory: optimal number of threads = (ratio of thread wait time to thread CPU time + 1) * number of cpus

Runtime.getRuntime().availableProcessors();// Get the number of current CPU cores
Copy the code

In a word, in a word, or according to the business situation, combined with the actual, to make the corresponding configuration.

The resources

  • The Art of Concurrent Programming in Java
  • Coding Efficient Java Development Manual

Young man wake up, your girlfriend ran away with someone else!!