全局执行器服务

Global Executor Service

我想使用一个公共线程池,它可以在我的应用程序中随处使用。我要在主 class 中创建一个静态执行器服务吗?然后在需要的地方使用它?目前我的主要 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);
}

我的线程池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;
}

}

在我的实现中 class(GetDetails.java),我通过以下方式获取执行程序。

    public void getDetails()
    {
    int corePoolSize=25;
    int maxPoolSize=50;
    int KeepAliveTimeMs=1000;
    ExecutorService executor = MyMainApplication.getExecutor(corePoolSize, 
    maxPoolSize, keepAlive);
    ..........
    ..........
    executor.execute(runnableTask);
   }

我担心的是每次调用 getDetails() 时,它是否会创建一个带有一组新池的新执行程序服务。例如在生产环境中。如果有大约 100 个 getDetails() 请求,它会导致创建 100 个执行程序服务,每个执行程序服务都有自己的一组线程池,即 100 *(25 corePoolSize、50 maxPoolSize、1000 keepTimeAlive)。或者所有请求都将使用带有 common/same 线程池的公共执行程序服务,该线程池为 (25 corePoolSize, 50 maxPoolSize, 1000 keepTimeAlive)。为了实现这一点,我将 main 中的 getExecutor() 设为静态。我做得对吗?

你的担心是对的,这段代码会在你每次调用 getDetails 时创建一个新的线程池。最终,如果对其进行足够多的调用,您将 运行 超出线程。

您可以将 ExecutorService 保存在静态变量中并检索保存的引用,而不是每次都创建一个新引用。或者,您可以使用依赖注入,让 DI 框架将其注入到需要的地方。

创建线程是expensive,而池可以重新使用现有线程,从而提高性能。

为每个请求创建一个线程池违反了它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.

所以还是弄个单例线程池到处用吧


如果您决定为每个请求创建一个线程池,请确保最终 shutdown it after all tasks finish, otherwise the pool will not be garbage collected, which leads to