preface

This section focuses on thread pool rejection policies

series

  • Thread Pool Series – (1) Background
  • Thread pool series – (2) Thread pool status
  • Thread pool series – (3) Rejection policy
  • Thread Pool series – (4) Workflow
  • Thread pool series – (5) Shutdown && shutdownNow
  • Thread pool – (6) Submit

What is a rejection strategy

Understand why thread pools have a rejection policy in the first place. That is, what is the context of his appearance. Those of you who know thread pools know this. The thread pool construction parameter has a rejection policy

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          longkeepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, // Interface to reject policy RejectedExecutionHandler handler) {
Copy the code

To refuse. This means that certain conditions are not met, and the same goes for thread pools. When the number of threads exceeds maximumPoolSize. The task is rejected. It protects the thread pool

What are the rejection strategies

RejectedExecutionHandler is itself an interface. The following

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
Copy the code

The thread pool itself provides four different rejection policies

Implementation principle of Java thread pool and its practice in Meituan business

AbortPolicy

You can see that. Very simple and crude, just throw an exception.

DiscardPolicy

Hey, nothing. Ask nothing. The mission was rejected and then it was rejected. I don’t want to give you a hint. It’s like throwing the task away

DiscardOldestPolicy

If the thread pool is still running. Then cancel the first task in the blocking queue, which is a bit confusing when executing the current task. The author wrote a simple test code. Be able to describe it more clearly. DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy: DiscardOldestPolicy And then print. To observe the

Click here to see the complete test code

public class Main {

    public static class CustomDiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public CustomDiscardOldestPolicy(a) {}/**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if(! e.isShutdown()) { System.out.println("Rejected assignment." + r.toString());
                Runnable runnable = e.getQueue().poll();
                if(runnable ! =null)
                    System.out.println("Tasks received in the queue" + runnable.toString());
                else
                    System.out.println("Task null in queue"); e.execute(r); }}}public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1.2.60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(2),
                new CustomDiscardOldestPolicy()
        );

        for (int i = 0; i < 5; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run(a) {
                    System.out.println("Mission Execution -- Start" + Thread.currentThread().getName() + " 任务 " + this.toString());
                    try {
                        Thread.sleep(1000);
                    } catch(InterruptedException e) { e.printStackTrace(); }}}; System.out.println("Add task"+ runnable.toString()); pool.execute(runnable); }}}Copy the code

In the test code above. The author controls the maximum number of threads at 2. The number of core threads is limited to 1. And a queue ArrayBlockingQueue with a length is selected. Set its length to 2.

  • When task 1 is added in. Since the number of core threads is 1, a new thread is created to execute the task.
  • When task 2 is added in. It was added to the queue because the number of core threads exceeded 1. There is a task 2 in the queue
  • When task 3 is added in. In the same way. Is added to the queue. Now there are two tasks in the queue.
  • When task 4 is added in. At this point, the queue is full. So determine if the maximum number of threads has been exceeded. Beyond that, reject the strategy outright.

CallerRunsPolicy

Default reject policy

You can see a defaultHandler rejection policy in the thread pool constructor

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);
}
Copy the code

DefaultHandler creates an AbortPolicy for us. This is also the default thread pool policy. Just throw an exception

private static final RejectedExecutionHandler defaultHandler =
    new AbortPolicy();
Copy the code