Reputation: 77
I want to use a common thread pool that can be used throughout my application wherever I want. Shall I create a static Executor service in the main class. Then use it wherever needed? Currently I have this in my main class(MyMainApplication.java)
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static final ThreadPoolExecutor getExecutor(int corePoolSize, int maxPoolSize, int keepAlive) {
return ThreadPools.getExecutor(corePoolSize, maxPoolSize, keepAlive);
}
My threadpool class:
@Component
public class ThreadPools {
private static final int DEFAULT_CORE_POOL_SIZE = 5;
private static final int DEFAULT_MAX_POOL_SIZE = 10;
private static final int DEFAULT_KEEP_ALIVE_MS = 240;
private static int corePoolSize = DEFAULT_CORE_POOL_SIZE;
private static int maxPoolSize = DEFAULT_MAX_POOL_SIZE;
private static int poolKeepAliveInMillis = DEFAULT_KEEP_ALIVE_MS;
public static ThreadPoolExecutor getExecutor(int cpSize, int maxSize, int msTime) {
if (cpSize != 0) {
setCorePoolSize(cpSize);
}
if (maxSize != 0) {
setMaxPoolSize(maxSize);
}
if (msTime != 0) {
setKeepAlive(msTime);
}
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, poolKeepAliveInMillis, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(corePoolSize));
}
public static void setCorePoolSize(int size) {
ThreadPools.corePoolSize = size;
}
public static void setMaxPoolSize(int size) {
ThreadPools.maxPoolSize = size;
}
public static void setKeepAlive(int time) {
ThreadPools.poolKeepAliveInMillis = time;
}
}
And in my implementation class(GetDetails.java), I am getting the executor the following way.
public void getDetails()
{
int corePoolSize=25;
int maxPoolSize=50;
int KeepAliveTimeMs=1000;
ExecutorService executor = MyMainApplication.getExecutor(corePoolSize,
maxPoolSize, keepAlive);
..........
..........
executor.execute(runnableTask);
}
My concern is for each call to the getDetails(), will it create a new executor service with a new set of pool. so for example in production environment. if there are about 100 requests for getDetails() , will it result in creating 100 executor service with each having a their own set of the threadpool which is 100 * (25 corePoolSize, 50 maxPoolSize, 1000 keepTimeAlive). or will all the request use a common executor service with a common/same threadpool which is (25 corePoolSize, 50 maxPoolSize, 1000 keepTimeAlive). To achieve this I have made the getExecutor() in main as static. Am I doing it correctly?
Upvotes: 3
Views: 2121
Reputation: 28289
Creating threads is expensive, while the pool can re-use existing threads, which improves the performance.
Creating a thread pool for every request is violation of it's design:
Thread pools address two different problems:
they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead,
and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks.
So it's better to make a singlton thread pool and use it everywhere.
If you do decide to create a thread pool for every request, make sure to shutdown it after all tasks finish, otherwise the pool will not be garbage collected, which leads to OutOfMemory eventually.
Upvotes: 2
Reputation: 96454
You’re right to be concerned, this code will create a new threadpool every time you call getDetails. Eventually with enough calls to it you’ll run out of threads.
You could save the ExecutorService in a static variable and retrieve the saved reference instead of creating a new one every time. Alternatively you could use dependency injection and let the DI framework inject it where it’s needed.
Upvotes: 2