3

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?

Jack
  • 67
  • 1
  • 6

2 Answers2

2

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.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • thank you for the response. I modified the code to create a public static ExecutorService variable in my main class. I will be retreiving it from the getDetails() api. Do I need to shutdown the ExecutorService? If yes, when/where do I shut it down. Since it is static, if I shut it down, the requests after the shutdown will be rejected right? so is it fine to avoid calling shutdown()? – Jack Oct 31 '18 at 05:48
  • @Jack: you should call shutdown because otherwise the pool's thread will keep the JVM alive. Tasks submitted to the pool should handle interruption so that the pool can tell them to finish. – Nathan Hughes Oct 31 '18 at 13:25
  • In my main class I have created a method with "PreDestroy" annotation. I am shutting down the executor service here. that should be fine right? – Jack Nov 01 '18 at 16:26
2

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.

xingbin
  • 27,410
  • 9
  • 53
  • 103
  • thank you for the response. I decided to create a static executorService variable in my main class instead rather than creating a new threadpool for each requests. I will be using it from the implementation class (getDetails()) API. Do I still need to shutdown this executorservice if it is static? – Jack Oct 31 '18 at 05:51
  • @Jack You can shutdown it when you want to terminate the whole application. – xingbin Oct 31 '18 at 09:29