【问题标题】:ThreadPoolTaskExecutor blocks feeder thread foreverThreadPoolTask​​Executor 永远阻塞供给线程
【发布时间】:2022-11-22 09:21:54
【问题描述】:

我试图让一个线程加载记录(比如从数据库)。该线程将记录馈送到处理这些单独任务的线程池中。

我原以为这段代码可以工作,但它打印数字直到 60,然后停止。

ThreadPoolTaskExecutor accountLoaderTaskExecutor = new ThreadPoolTaskExecutor();
accountLoaderTaskExecutor.setCorePoolSize(1);
accountLoaderTaskExecutor.setMaxPoolSize(1);
accountLoaderTaskExecutor.initialize();

ThreadPoolTaskExecutor accountDeletionTaskExecutor = new ThreadPoolTaskExecutor();
accountDeletionTaskExecutor.setCorePoolSize(10);
accountDeletionTaskExecutor.setMaxPoolSize(10);
accountDeletionTaskExecutor.setQueueCapacity(50);
accountDeletionTaskExecutor.initialize();

accountLoaderTaskExecutor.submit(() -> {
    List<Integer> customerAccountIds = getCustomerAccountIds();  // return 1000s integers
    customerAccountIds.forEach(id -> {
        accountDeletionTaskExecutor.submit(() -> {
            try {
                System.out.println(id);
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    });
});

Thread.currentThread().join();

我原以为 accountLoaderTaskExecutor 线程会在 accountDeletionTaskExecutor.submit 上阻塞,但随后继续处理记录,直到耗尽所有 customerAccountId。

【问题讨论】:

    标签: java multithreading concurrency


    【解决方案1】:

    如果注释“返回 1000 秒整数”意味着您有数千个 id,那么您编写的代码会将数千个任务排队到线程池,然后继续执行 Thread.currentThread().join(),这绝对什么都不做,因为将当前线程加入到自身是无意义:你只能加入不同的线程。

    然后,我假设您退出应用程序,默认行为可能是在应用程序退出时终止所有线程池。 (我不确定,我在猜测。)

    您观察到的开始启动的 60 个任务可能会设法启动,而其余的数千个任务正在排队。

    要验证这是否正在发生,您可以尝试将对 join() 的调用替换为 Thread.sleep( 1000 ) 并查看是否观察到更多任务正在启动。

    如果是这种情况,那么解决问题的一种方法可能是添加适当的正常线程池关闭(等待所有排队任务首先完成的那种。)

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      • 1970-01-01
      相关资源
      最近更新 更多