diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java index 26dcec6370..d95fef71f2 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,14 +73,14 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport private int keepAliveSeconds = 60; - private int queueCapacity = Integer.MAX_VALUE; - private boolean allowCoreThreadTimeOut = false; - private boolean exposeUnconfigurableExecutor = false; - private boolean prestartAllCoreThreads = false; + private int queueCapacity = Integer.MAX_VALUE; + + private boolean exposeUnconfigurableExecutor = false; + @Nullable private ExecutorService exposedExecutor; @@ -120,6 +120,16 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport this.allowCoreThreadTimeOut = allowCoreThreadTimeOut; } + /** + * Specify whether to start all core threads, causing them to idly wait for work. + *
Default is "false". + * @since 5.3.14 + * @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads + */ + public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) { + this.prestartAllCoreThreads = prestartAllCoreThreads; + } + /** * Set the capacity for the ThreadPoolExecutor's BlockingQueue. * Default is {@code Integer.MAX_VALUE}. @@ -132,17 +142,6 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport this.queueCapacity = queueCapacity; } - /** - * Specify whether this FactoryBean should prestart all threads - * for the created executor. - *
Default is "false". - * Switch this flag to "true" to prestart the threads allocated for the current executor - * @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads - */ - public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) { - this.prestartAllCoreThreads = prestartAllCoreThreads; - } - /** * Specify whether this FactoryBean should expose an unconfigurable * decorator for the created executor. @@ -166,7 +165,6 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport if (this.allowCoreThreadTimeOut) { executor.allowCoreThreadTimeOut(true); } - if (this.prestartAllCoreThreads) { executor.prestartAllCoreThreads(); } diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java index 486e0c7cdd..928814524c 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,6 +94,8 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport private boolean allowCoreThreadTimeOut = false; + private boolean prestartAllCoreThreads = false; + @Nullable private TaskDecorator taskDecorator; @@ -197,6 +199,16 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport this.allowCoreThreadTimeOut = allowCoreThreadTimeOut; } + /** + * Specify whether to start all core threads, causing them to idly wait for work. + *
Default is "false".
+ * @since 5.3.14
+ * @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads
+ */
+ public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) {
+ this.prestartAllCoreThreads = prestartAllCoreThreads;
+ }
+
/**
* Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable}
* about to be executed.
@@ -256,6 +268,9 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
if (this.allowCoreThreadTimeOut) {
executor.allowCoreThreadTimeOut(true);
}
+ if (this.prestartAllCoreThreads) {
+ executor.prestartAllCoreThreads();
+ }
this.threadPoolExecutor = executor;
return executor;
diff --git a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBeanTests.java
index c5731e3139..d350341a8c 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBeanTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBeanTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,11 +25,11 @@ import java.util.concurrent.ThreadPoolExecutor;
import org.junit.jupiter.api.Test;
-import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.GenericApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -37,6 +37,8 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
+ * Tests for {@link ThreadPoolExecutorFactoryBean}.
+ *
* @author Juergen Hoeller
*/
class ThreadPoolExecutorFactoryBeanTests {
@@ -53,19 +55,25 @@ class ThreadPoolExecutorFactoryBeanTests {
}
@Test
- public void executorWithPreStartedThreads() throws Exception {
- ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ExecutorConfigWithPreStartedThreads.class);
- ThreadPoolExecutor executor = context.getBean("childExecutor", ThreadPoolExecutor.class);
-
- verify(executor).prestartAllCoreThreads();
+ void executorWithDefaultSettingsDoesNotPrestartAllCoreThreads() {
+ GenericApplicationContext context = new GenericApplicationContext();
+ context.registerBean("taskExecutor", ThreadPoolExecutorFactoryBean.class, TestThreadPoolExecutorFactoryBean::new);
+ context.refresh();
+ ThreadPoolExecutor threadPoolExecutor = context.getBean(ThreadPoolExecutor.class);
+ verify(threadPoolExecutor, never()).prestartAllCoreThreads();
}
@Test
- public void executorWithNoPreStartedThreads() throws Exception {
- ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ExecutorConfigWithNoPreStartedThreads.class);
- ThreadPoolExecutor executor = context.getBean("childExecutor", ThreadPoolExecutor.class);
-
- verify(executor, never()).prestartAllCoreThreads();
+ void executorWithPrestartAllCoreThreads() {
+ GenericApplicationContext context = new GenericApplicationContext();
+ context.registerBean("taskExecutor", ThreadPoolExecutorFactoryBean.class, () -> {
+ TestThreadPoolExecutorFactoryBean factoryBean = new TestThreadPoolExecutorFactoryBean();
+ factoryBean.setPrestartAllCoreThreads(true);
+ return factoryBean;
+ });
+ context.refresh();
+ ThreadPoolExecutor threadPoolExecutor = context.getBean(ThreadPoolExecutor.class);
+ verify(threadPoolExecutor).prestartAllCoreThreads();
}
@Configuration
@@ -78,37 +86,8 @@ class ThreadPoolExecutorFactoryBeanTests {
}
- @Configuration
- public static class ExecutorConfigWithPreStartedThreads {
+ private static class TestThreadPoolExecutorFactoryBean extends ThreadPoolExecutorFactoryBean {
- @Bean
- public ThreadPoolExecutorFactoryBean executorChildFactory() {
- ThreadPoolExecutorFactoryBeanMockingChild threadPoolExecutorFactoryBeanMockingChild = new ThreadPoolExecutorFactoryBeanMockingChild();
- threadPoolExecutorFactoryBeanMockingChild.setPrestartAllCoreThreads(true);
- return threadPoolExecutorFactoryBeanMockingChild;
- }
-
- @Bean
- public ExecutorService childExecutor() {
- return executorChildFactory().getObject();
- }
- }
-
- @Configuration
- public static class ExecutorConfigWithNoPreStartedThreads {
-
- @Bean
- public ThreadPoolExecutorFactoryBean executorChildFactory() {
- return new ThreadPoolExecutorFactoryBeanMockingChild();
- }
-
- @Bean
- public ExecutorService childExecutor() {
- return executorChildFactory().getObject();
- }
- }
-
- private static class ThreadPoolExecutorFactoryBeanMockingChild extends ThreadPoolExecutorFactoryBean {
@Override
protected ThreadPoolExecutor createExecutor(
int corePoolSize, int maxPoolSize, int keepAliveSeconds, BlockingQueue