Skip to content

Commit

Permalink
Expose prestartAllCoreThreads on ExecutorService
Browse files Browse the repository at this point in the history
  • Loading branch information
fededonna authored and snicoll committed Nov 23, 2021
1 parent 2271b60 commit 2c53e9e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport

private int keepAliveSeconds = 60;

private boolean allowCoreThreadTimeOut = false;

private int queueCapacity = Integer.MAX_VALUE;

private boolean allowCoreThreadTimeOut = false;

private boolean exposeUnconfigurableExecutor = false;

private boolean prestartAllCoreThreads = false;

@Nullable
private ExecutorService exposedExecutor;

Expand Down Expand Up @@ -130,6 +132,17 @@ public void setQueueCapacity(int 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
* decorator for the created executor.
Expand All @@ -154,6 +167,10 @@ protected ExecutorService initializeExecutor(
executor.allowCoreThreadTimeOut(true);
}

if (this.prestartAllCoreThreads) {
executor.prestartAllCoreThreads();
}

// Wrap executor with an unconfigurable decorator.
this.exposedExecutor = (this.exposeUnconfigurableExecutor ?
Executors.unconfigurableExecutorService(executor) : executor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,25 @@

package org.springframework.scheduling.concurrent;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
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.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 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
Expand All @@ -44,6 +52,21 @@ void defaultExecutor() throws Exception {
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
static class ExecutorConfig {
Expand All @@ -55,4 +78,45 @@ ThreadPoolExecutorFactoryBean executor() {

}

@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);
}
}


}

0 comments on commit 2c53e9e

Please sign in to comment.