为什么 jvm 在 fixedThreadPool 的情况下重新创建线程池而在 cachedThreadPool 的情况下不这样做?

Why jvm recreate thread pool in case fixedThreadPool and don't do it in case of cachedThreadPool?

我有代码示例:

public class ThreadPoolTest {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            if (test() != 5 * 100) {
                throw new RuntimeException("main");
            }
        }
        test();

    }

    private static long test() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        CountDownLatch countDownLatch = new CountDownLatch(100 * 5);
        Set<Thread> threads = Collections.synchronizedSet(new HashSet<>());
        AtomicLong atomicLong = new AtomicLong();
        for (int i = 0; i < 5 * 100; i++) {
            Thread.sleep(100);
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        threads.add(Thread.currentThread());
                        atomicLong.incrementAndGet();
                        countDownLatch.countDown();
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        System.out.println(e);
                    }


                }
            });
        }
        executorService.shutdown();
        countDownLatch.await();
        if (threads.size() != 100) {
            throw new RuntimeException("test");
        }
        return atomicLong.get();
    }
}

我特别申请了长期工作

我看到了 jvisualVM。
每次重新创建间隙线程池。

几分钟后我看到:

但是如果我使用 newCachedThreadPool 而不是 newFixedThreadPool 我会看到恒定的图片:

你能解释一下这种行为吗?

P.S.

问题是代码中出现异常,第二次迭代没有开始

回答您的问题;看看这里:

private static long test() throws InterruptedException {
  ExecutorService executorService = Executors.newFixedThreadPool(100);

JVM 在 test() 的每个 运行 期间创建一个新的线程池,因为您告诉它这样做。

换句话说:如果你打算re-use相同的线程池,那么避免creating/shutting下来一直都是你的实例。

从这个意义上说,简单的解决方法是:将 ExecutorService 的创建移动到您的 main() 方法中;并将服务作为参数传递给您的 test() 方法。

编辑:关于您对缓存线程池与固定线程池的最后评论;你可能想看看这个 question.

因为您在代码中要求它这样做? :)

尝试将 Pool 创建代码移到测试之外。

来自文档:

newFixedThreadPool

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.

newCachedThreadPool

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.