Java ThreadPoolExecutor 能同时运行的最大线程数问题

发布于 2022-09-12 23:29:42 字数 2030 浏览 22 评论 0

关于线程池参数的解释:

image.png
我这样设置,同时运行的线程数为什么大于maximumPoolSize,不应该只有一个线程同时运行吗?

        THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
                1,
                1,
                60,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

执行方法:

private static void testThreadPoolExecutor() {
        THREAD_POOL_EXECUTOR.execute(() -> {
            System.out.println("线程1");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        THREAD_POOL_EXECUTOR.submit(() -> {
            System.out.println("线程2");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        THREAD_POOL_EXECUTOR.execute(() -> {
            System.out.println("线程3");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        THREAD_POOL_EXECUTOR.execute(() -> {
            System.out.println("线程4");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        THREAD_POOL_EXECUTOR.execute(() -> {
            System.out.println("线程5");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        THREAD_POOL_EXECUTOR.shutdown();
    }

结果,同时运行了两个线程(总是比maximumPoolSize大1),为什么不是一个
image.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

网白 2022-09-19 23:29:42

首先,看一下你这个五个线程$n,实际上称之为任务更合适。

  1. 线程1直接创建一个线程来执行
  2. 线程2进入队列

这两个是没有问题的。

然后,看线程3,这个时候,线程数队列都达到最大了,使用reject策略。
CallerRunsPolicy:

public static class CallerRunsPolicy implements RejectedExecutionHandler {
       
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

直接在当前线程执行run方法。
这里又多了一个线程,就是执行这段代码的线程,可能就是你的主线程

这就是为什么有两个线程的原因。

后续的线程4线程5会在线程池线程当前线程这两个线程中运行 。

如果你使用了AbortPolicy策略,在线程3时,就直接报异常了:

public static class AbortPolicy implements RejectedExecutionHandler {
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

同样的,由于线程1要执行3秒,后续的线程4线程5都会直接抛出异常。当然,你要处理这个异常,要不然,程序就中断了。
线程1执行结束,执行队列中的线程2

筑梦 2022-09-19 23:29:42

因为你用的是 CallerRunsPolicy,就是线程池不够的时候用掉用方的线程执行
改成 AbortPolicy 就会拒绝执行了

余厌 2022-09-19 23:29:42

你的饱和策略,如果不够执行,就会交由主线程完成。多线程的情况下,通知运行的线程至少都有2个吧,一个主线程,一个执行线程。这没什么奇怪你,你设置的是线程池,不包含主线程。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文