A thread pool is a pool of tasks. It is a pool of tasks. It is a pool of tasks. Let’s talk about that today. How does thread pooling work? What are the denial policies for thread pools?

Thread pools execute processes

Execute () : execute() : execute() : execute() : execute()

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // The number of working threads is smaller than the number of core threads
    if (workerCountOf(c) < corePoolSize) {
        // Create a new thread to perform this task
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // Check if the thread pool is running, and if so, add tasks to the queue
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // Check whether the thread pool is running again to prevent the thread pool from closing after the first check is passed
        // If the status is not running, the newly queued task is removed
        if (! isRunning(recheck) && remove(command))
            reject(command);
        // If the number of threads in the thread pool is 0 (this happens when corePoolSize is set to 0)
        else if (workerCountOf(recheck) == 0)
            addWorker(null.false); // Create a new thread to execute the task
    }
    // The core threads are busy and the queues are full. The attempt to start a new thread failed
    else if(! addWorker(command,false)) 
        // Execute the reject policy
        reject(command);
}

Copy the code

As we can see from the above source code, when the task comes,The execution flow of the thread pool is as follows: Is the number of current threads greater than the number of core threads? If the result is false, create a new thread and execute the task; If the result is true, is the task queue full? If the result is false, the task is added to the task queue to wait for the thread to execute. Otherwise, does the current number of threads exceed the maximum number? If the result is false, a new thread executes the task, otherwise the thread pool’s rejection policy is executed, as shown in the figure below:

Thread pool rejection policy

When there are too many tasks and the task queue of the thread pool is full, the thread pool reject policies are implemented. The default reject policies of the thread pool are as follows:

  1. AbortPolicy: AbortPolicy. The thread pool throws an exception and aborts execution of the task.
  2. CallerRunsPolicy: Assign the task to the (main) thread that added the task;
  3. DiscardPolicy: Ignore this task, ignore the last task;
  4. DiscardOldestPolicy: Ignores the earliest task and is the first task to be queued.

The default reject policy is AbortPolicy.

DiscardPolicy Rejects the policy

Next, we take DiscardPolicy to ignore this task and the latest task as an example to demonstrate the specific use of the rejection policy. The implementation code is as follows:

public static void main(String[] args) {
    // The specific method of the task
    Runnable runnable = new Runnable() {
        @Override
        public void run(a) {
            System.out.println("Current task executed at :" + new Date() +
                               "Execution thread :" + Thread.currentThread().getName());
            try {
                / / wait for 1 s
                TimeUnit.SECONDS.sleep(1);
            } catch(InterruptedException e) { e.printStackTrace(); }}};// Create a thread with a task queue of length 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1.1.100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.DiscardPolicy());
    // Add and execute four tasks
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // Close the thread pool when the task is complete
    threadPool.shutdown();
}
Copy the code

The execution results of the above procedures are as follows:As can be seen from the above execution results, four tasks are added to the thread pool, but the thread pool only executes two tasks and ends. The other two tasks execute the rejection policy and DiscardPolicy is ignored, which is the function of the rejection policy.

AbortPolicy Rejects the policy

AbortPolicy AbortPolicy is the default denial policy of the JDK. The thread pool throws an exception and aborts execution of the task.

public static void main(String[] args) {
    // The specific method of the task
    Runnable runnable = new Runnable() {
        @Override
        public void run(a) {
            System.out.println("Current task executed at :" + new Date() +
                               "Execution thread :" + Thread.currentThread().getName());
            try {
                / / wait for 1 s
                TimeUnit.SECONDS.sleep(1);
            } catch(InterruptedException e) { e.printStackTrace(); }}};// Create a thread with a task queue of length 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1.1.100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.AbortPolicy()); // Explicitly specify a rejection policy, or you can ignore this setting, which is the default rejection policy
    // Add and execute four tasks
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // Close the thread pool when the task is complete
    threadPool.shutdown();
}
Copy the code

The execution results of the above procedures are as follows:Add the thread pool can be seen from the results, the four tasks, the thread pool to perform two tasks, the other two task execution aborted strategy, and throw the abnormal RejectedExecutionException refused to carry out.

User-defined rejection policy

Of course besides JDK provides four kinds of refusal strategies, we also can realize through new RejectedExecutionHandler, rewrite rejectedExecution way to implement custom refused to strategy, implementation code is as follows:

public static void main(String[] args) {
    // The specific method of the task
    Runnable runnable = new Runnable() {
        @Override
        public void run(a) {
            System.out.println("Current task executed at :" + new Date() +
                               "Execution thread :" + Thread.currentThread().getName());
            try {
                / / wait for 1 s
                TimeUnit.SECONDS.sleep(1);
            } catch(InterruptedException e) { e.printStackTrace(); }}};// Create a thread with a task queue of length 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1.1.100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new RejectedExecutionHandler() {
                                                               @Override
                                                               public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                                                                   // Perform operations related to user-defined rejection policies
                                                                   System.out.println("I am a custom rejection policy ~"); }});// Add and execute four tasks
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
}
Copy the code

The execution results of the above procedures are as follows:

conclusion

The execution process of a thread pool has three important judgment points (the order of judgment is later) : the number of current threads and core threads, whether the current task queue is full, and whether the number of current threads has reached the maximum number of threads. If the result is true after the above three judgments, the thread pool rejection policy will be executed. The JDK provides four rejection strategies, and you can also customize the rejectedExecution method by rewriting the New RejectedExecutionHandler.

Judge right and wrong from yourself, praise to listen to others, gain and loss in the number.

Public number: Java interview analysis

Interview collection: gitee.com/mydb/interv…