Talk to chatGpt about what will happen to the thread pool of the old node when it is released

I. Introduction

        Today my colleague asked a question, what happens to the thread pool in the old node service every time the system is released, and will the tasks in the queue be executed?

c78350c33c994504a4655800ee0ad1cb.png

        The blogger has always believed that graceful exit must wait for the execution to be completed before exiting. As a result, he chatted with chatGpt, and there were twists and turns.

2. Analysis

1、ThreadPoolExecutor的退出

        The blogger asked: What happens to the tasks in the queue of the thread pool when the java service exits?

        chatGpt answer: When the Java service exits, the processing method of the unexecuted tasks (tasks in the queue) in the thread pool depends on the type and configuration of the thread pool. For standard ThreadPoolExecutor, when a Java service exits, the thread pool tries to complete tasks that have not yet been executed. It waits for tasks in the queue to be executed, and processes each task one by one until the queue is empty. This means that the thread pool waits for all submitted tasks to complete before shutting down the thread pool.

        By default, ThreadPoolExecutornon-daemon threads are used, so threads in the thread pool will not block the exit of the Java service, but will continue to execute tasks until the queue is empty. If you want to stop the task in the thread pool immediately when the Java service exits, you can set the thread pool thread as a daemon thread (by setting setDaemon(true)), so that when the main thread exits, the daemon thread will be interrupted and stop the execution of the task.

        Looking at it this way, it is consistent with the blogger's idea, but the blogger thought about another problem, usually ThreadPoolExecutor it is entrusted to spring for hosting, and spring has to be considered.

@Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        // 创建自定义的 ThreadPoolExecutor
        // ...
    }

2. Spring hostingThreadPoolExecutor的退出

        The blogger asked: Will Spring Boot not wait for the ThreadPoolExecutor defined by @bean to finish executing the task?

        What chatGpt answered is: In Spring Boot, the @Beandefined ThreadPoolExecutorones will not wait for the tasks to be executed by default. When a Spring Boot application shuts down, it triggers a shutdown hook that automatically shuts down all objects in the Spring container, including @Beanthread pools defined via .

        By default, Spring Boot will call the thread pool shutdown()method to close the thread pool, but it will not wait for all tasks in it to be executed. Executing tasks will continue to execute, while unexecuted tasks will be discarded.

        This stunned the bloggers. If you do this, it’s not that the data in the queue heap is all gone. If you encounter some traffic once you publish it, the traffic will be completely abolished. But is this really the case?

3. The difference between shutdownNow and shutdown

        Since spring uses ThreadPoolExecutorthe shutdown method to close the thread pool, let's go back to the source code and see. As a result, there is a shutdownNow method, which obviously brings a difference between violence and elegance.

        See the difference between the two methods

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }
public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

        The big difference is:

        1. shutdownNow will take out the task and return

        2. shutdownNow will set the STOP state through cas, and shutdown will set the SHUTDOWN state

        Obviously the difference is in this state, so does this state affect the queue tasks? Look at the method of obtaining queue tasks

private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

        Obviously, the point is if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())), when STOP, the task will not be returned to the worker, but when SHUTDOWN, the queue is empty. Return, so the shutdown method will continue to execute the tasks in the queue, which leads to a different conclusion from what chatGpt said!

4、bean的destroyMethod

        But there is still a problem, the destruction method of the object generally specifies shutdown on the object

@Bean(name = "handoverExecutor", destroyMethod = "shutdown")
    public ThreadPoolExecutor handoverExecutor() {
        return new ThreadPoolExecutor(20, 30,
                600, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy());
    }

        But sometimes it will not be specified, and the default will be used, so what is the default? 

String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;

public static final String INFER_METHOD = "(inferred)";

        What is the method of this inferred? If you trace the place where the reflection method is taken, you can see that the shutdown method is taken without close, and ThreadPoolExecutor does not have a close method, so it uses shutdown by default.

String destroyMethodName = beanDefinition.getDestroyMethodName();
		if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
				(destroyMethodName == null && closeableInterface.isInstance(bean))) {
			// Only perform destroy method inference or Closeable detection
			// in case of the bean not explicitly implementing DisposableBean
			if (!(bean instanceof DisposableBean)) {
				try {
					return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
				}
				catch (NoSuchMethodException ex) {
					try {
						return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
					}
					catch (NoSuchMethodException ex2) {
						// no candidate destroy method found
					}
				}
			}
			return null;
		}
		return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);

3. Summary

        chatGpt's knowledge search in a single aspect is indeed relatively in-depth and accurate. It is much better than filtering a large number of speeches directly from Baidu, Google, and technical communities. It can be said to be an excellent AI search engine.

        However, the weakness of chatGpt is that it cannot analyze. Once combined with various knowledge, the information given may be wrong. Students should read more authoritative books, source code, and communicate with technical communities, and do not blindly trust search engines.

Guess you like

Origin blog.csdn.net/m0_69270256/article/details/130731138
Recommended