Expose prestartAllCoreThreads on ExecutorService
See gh-1246
This commit is contained in:
parent
2271b6078e
commit
2c53e9e308
|
@ -73,12 +73,14 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
|
|
||||||
private int keepAliveSeconds = 60;
|
private int keepAliveSeconds = 60;
|
||||||
|
|
||||||
private boolean allowCoreThreadTimeOut = false;
|
|
||||||
|
|
||||||
private int queueCapacity = Integer.MAX_VALUE;
|
private int queueCapacity = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private boolean allowCoreThreadTimeOut = false;
|
||||||
|
|
||||||
private boolean exposeUnconfigurableExecutor = false;
|
private boolean exposeUnconfigurableExecutor = false;
|
||||||
|
|
||||||
|
private boolean prestartAllCoreThreads = false;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ExecutorService exposedExecutor;
|
private ExecutorService exposedExecutor;
|
||||||
|
|
||||||
|
@ -130,6 +132,17 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
this.queueCapacity = queueCapacity;
|
this.queueCapacity = queueCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify whether this FactoryBean should prestart all threads
|
||||||
|
* for the created executor.
|
||||||
|
* <p>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
|
* Specify whether this FactoryBean should expose an unconfigurable
|
||||||
* decorator for the created executor.
|
* decorator for the created executor.
|
||||||
|
@ -154,6 +167,10 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
executor.allowCoreThreadTimeOut(true);
|
executor.allowCoreThreadTimeOut(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.prestartAllCoreThreads) {
|
||||||
|
executor.prestartAllCoreThreads();
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap executor with an unconfigurable decorator.
|
// Wrap executor with an unconfigurable decorator.
|
||||||
this.exposedExecutor = (this.exposeUnconfigurableExecutor ?
|
this.exposedExecutor = (this.exposeUnconfigurableExecutor ?
|
||||||
Executors.unconfigurableExecutorService(executor) : executor);
|
Executors.unconfigurableExecutorService(executor) : executor);
|
||||||
|
|
|
@ -16,17 +16,25 @@
|
||||||
|
|
||||||
package org.springframework.scheduling.concurrent;
|
package org.springframework.scheduling.concurrent;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.RejectedExecutionHandler;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
@ -44,6 +52,21 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void executorWithPreStartedThreads() throws Exception {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ExecutorConfigWithPreStartedThreads.class);
|
||||||
|
ThreadPoolExecutor executor = context.getBean("childExecutor", ThreadPoolExecutor.class);
|
||||||
|
|
||||||
|
verify(executor).prestartAllCoreThreads();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void executorWithNoPreStartedThreads() throws Exception {
|
||||||
|
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ExecutorConfigWithNoPreStartedThreads.class);
|
||||||
|
ThreadPoolExecutor executor = context.getBean("childExecutor", ThreadPoolExecutor.class);
|
||||||
|
|
||||||
|
verify(executor, never()).prestartAllCoreThreads();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class ExecutorConfig {
|
static class ExecutorConfig {
|
||||||
|
@ -55,4 +78,45 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class ExecutorConfigWithPreStartedThreads {
|
||||||
|
|
||||||
|
@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<Runnable> queue,
|
||||||
|
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||||
|
|
||||||
|
return mock(ThreadPoolExecutor.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue