This is the 21st day of my participation in the August More Text Challenge

The thread pool ThreadPoolExecutor

role
  • The art of concurrent programming

    • Reduce resource consumption
    • Improve response speed
    • Improve thread manageability
  • Code out efficient Java development manuals

    • Use thread pool to manage and reuse lines, control the maximum concurrency, etc
    • Implement task thread queue cache policy and reject mechanism
    • Implement some time-related functions, such as timing execution, periodic execution, etc
    • Isolate the threading environment. For example, the transaction service and search service are on the same server, and two thread pools are opened respectively, so the resource consumption of the transaction thread is obviously larger. Therefore, by configuring an independent thread pool, the stirred transaction service is separated from the search service to avoid the interaction between the service threads
state
  • RUNNING: Can accept new tasks and process tasks in a blocking queue
  • SHUTDOWN: does not accept new tasks, but can process tasks in the blocking queue
  • STOPDo not accept new tasks, do not process tasks in the blocking queue, and interrupt the running task thread.
  • TIDYING: All tasks are terminated, and the worker thread is 0, in the state before closing
  • TERMINATED: Closed.
parameter
  • 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 a 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: Only the caller’s thread runs the task
    • DiscardOldestPolicy: Discards the latest task in the queue and executes the current task
    • DiscardPolicy: Not processed, discarded
    • 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
The sample code

Thread factory (which incidentally contains thread implementation classes for tasks)

public class UserThreadFactory implements ThreadFactory { private final String namePrefix; private final AtomicInteger nextId = new AtomicInteger(); // Define the thread group name. Public UserThreadFactory(String whatFeatureOfGroup) {this.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()); return thread; } } class Task implements Runnable{ private final AtomicLong count = new AtomicLong(0L); @Override public void run() { System.out.println("running_"+count.getAndIncrement()); }}Copy the code

The Rejection strategy (which seems perfunctory)

public class UserRejectHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println("task rejected. "+executor.toString());
    }
}
Copy the code

Thread pool master method (pool 1 has a rejection policy, but pool 2 does not, because queue 2 is strong enough, it seems that strength is everywhere)

public class UserThreadPool { public static void main(String[] args) { BlockingQueue queue1 = new LinkedBlockingQueue(2); BlockingQueue queue2 = new LinkedBlockingQueue(200); UserThreadFactory f1 = new UserThreadFactory(" 1 "); UserThreadFactory f2 = new UserThreadFactory(" 新 家 "); UserRejectHandler handler = new UserRejectHandler(); // The core thread is 1, the maximum thread is 2, RejectHandler ThreadPoolExecutor threadPoolFirst = new ThreadPoolExecutor(1,2,60, TimeUnit.SECONDS,queue1,f1,handler); // Create a second thread pool with the second thread factory instance, Here does not happen rejection policies ThreadPoolExecutor threadPoolSecond = new ThreadPoolExecutor (1,2,60, TimeUnit. SECONDS, queue2, f2, handler); Runnable task = new Task(); for (long i = 0; i < 200 ; i++) { threadPoolFirst.execute(task); threadPoolSecond.execute(task); }}}Copy the code
Be careful when using
  • 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
Configure thread pools properly

Analyze from different angles according to 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

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