“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

preface

Recently I was asked about this distinction in an interview and didn’t get a good answer. It happened to involve Spring’s asynchronous tasks, so I did a good job summarizing some of the source code.

The body of the

This class is a component of the Spring framework that encapsulates the JDK’s built-in ThreadPoolExecutor. Its underlying implementation is the JDK’s ThreadPoolExecutor.

A constructor

This class has no constructor and uses the default constructor.

attribute


    // Monitor lock, synchronized uses this object as the lock object
    private final Object poolSizeMonitor = new Object();
    // Number of core threads
	private int corePoolSize = 1;
    // Maximum number of threads
	private int maxPoolSize = Integer.MAX_VALUE;
    // Thread lifetime
	private int keepAliveSeconds = 60;
    // Initialize the queue capacity
	private int queueCapacity = Integer.MAX_VALUE;
    // Whether the number of core threads has idle time
	private boolean allowCoreThreadTimeOut = false;
	@Nullable // Task decorator
	private TaskDecorator taskDecorator;
	@Nullable / / thread pool
	private ThreadPoolExecutor threadPoolExecutor;
	
Copy the code

These are the default parameters for ThreadPoolTaskExecutor. The above parameter has fewer reject policy parameters than ThreadPoolExecutor. Of course, ThreadPoolTaskExecutor also provides set and GET methods for the above arguments.

methods

ThreadPoolTaskExecutor executes tasks by calling ThreadPoolExecutor instead of going into detail here.

InitializeExecutor method

This method is ThreadPoolTaskExecutor rewrites the, and this method is ExecutorConfigurationSupport an interface of a class.


    @Override
	protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
	    // Create a blocking queue
		BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);
		ThreadPoolExecutor executor;
		// If the decorator is not empty, override the execute method of ThreadPoolExecutor to decorate the task (decorator mode)
		if (this.taskDecorator ! =null) { 
			executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,queue, threadFactory, rejectedExecutionHandler) {
				@Override
				public void execute(Runnable command) {
					Runnable decorated = taskDecorator.decorate(command);
					if(decorated ! = command) { decoratedTaskMap.put(decorated, command); }super.execute(decorated); }}; }else {
			executor = new ThreadPoolExecutor(
					this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
					queue, threadFactory, rejectedExecutionHandler);
		}
		if (this.allowCoreThreadTimeOut) {
			executor.allowCoreThreadTimeOut(true);
		}
		this.threadPoolExecutor = executor;
		return executor;
	}
	
Copy the code

The above source code is not too difficult, as you can easily see if you have seen the ThreadPoolExecutor source code. The initial rejection policy parameters are passed in here, and everything else is available in ThreadPoolTaskExecutor.

This method also uses the decorator pattern, which can be noted here, and the source code for the decorator implementation is relatively simple.

Take a look at the source of the interface in the superclass ExecutorConfigurationSupport:


    // Interface in the parent class
    protected abstract ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);

    This method calls the initializeExecutor method
    public void initialize(a) {
		if (logger.isInfoEnabled()) {
			logger.info("Initializing ExecutorService" + (this.beanName ! =null ? "'" + this.beanName + "'" : ""));
		}
		if (!this.threadNamePrefixSet && this.beanName ! =null) {
			setThreadNamePrefix(this.beanName + "-");
		}
		/ / here's refusal strategies used by default new ThreadPoolExecutor AbortPolicy ();
		this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
	}
	// This method will be called after the bean is initialized
	@Override
	public void afterPropertiesSet(a) {
	    Call the initialize method
		initialize();
	}
	
Copy the code

ExecutorConfigurationSupport afterPropertiesSet implementing the InitializingBean interface methods. This method is called after the bean has been initialized by the container. The initializeExecutor method of ThreadPoolTaskExecutor is automatically called after the container initializes the bean, so it is not called manually.

Summary: Although we did not create ThreadPoolExecutor when we created ThreadPoolTaskExecutor; InitializeExecutor (ThreadPoolTaskExecutor) initializeExecutor (ThreadPoolTaskExecutor) It depends on how you use ThreadPoolTaskExecutor. If you put it into the container as a bean, you don’t need to call it manually. If 20 is not added to the container, it needs to be manually invoked.

Here is the code for the createQueue method


    protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
		if (queueCapacity > 0) {
			return new LinkedBlockingQueue<>(queueCapacity);
		}
		else {
			return newSynchronousQueue<>(); }}Copy the code

Note that the default parameter of the ThreadPoolTaskExecutor queue is integer. MAX_VALUE, which depends on your business

conclusion

How does ThreadPoolTaskExecutor differ from ThreadPoolExecutor?

  1. ThreadPoolExecutorIs the JDK’s own thread pool,ThreadPoolTaskExecutorIs spring
  2. ThreadPoolTaskExecutorrightThreadPoolExecutorCarried on the encapsulation, the specific task is still used by itselfThreadPoolExecutor
  3. Pay attention toThreadPoolTaskExecutorSome of the default parameters of the.
  4. If it is customThreadPoolTaskExecutorInstance, and is not added to the container, need to call the initialization method manually, if added to the container, do not need to call the initialization method manually.
  5. ThreadPoolTaskExecutorThe decorator mode is used to decorate the tasks, which can be referred to as related questions may be encountered in the interview