java 如果编译时任务计数未知,则执行器不会执行所有任务

java Executor not executing all tasks if task count is not known in compile time

我有一个非常简单的 java 代码片段:

  ExecutorService executor = null;          
      try {
          executor = Executors.newFixedThreadPool(4);             
          for (int i = 0; i < 10; i++) {                
              executor.submit( () -> processRule(rule_queue.poll()));           
            }
       }   

事情是这样的:如果我用 rule_queue.size() 替换 10(在我的例子中是 rule_queue 队列中的对象计数,那么并非所有任务都将被执行。

这是一个非常奇怪的行为,对于 1-2 个 fixedThreadPool 线程它会起作用,但是对于 3 个及以上的固定线程通常只会执行 5-7 个任务。

问题是队列中的对象计数来自数据库,因此我无法将其硬编码到 for 循环中。

方法processRule做一些数据库inserts/selects 所以我也不想打开太多threads/connections, 4-5 SQL 同时选择就足够了。

预先感谢您提供的任何帮助如何 运行 所有任务以及如何 运行 4 并行并将所有其他任务(最多 300 个)放入执行程序队列。

编辑:抱歉忘了写在这段代码之后另外两行是 executor.shutdown() 并等待完成。

我假设你更换了

for (int i = 0; i < 10; i++) {                
    executor.submit( () -> processRule(rule_queue.poll()));           
}

for (int i = 0; i < rule_queue.size(); i++) {
//                  ^^^^^^^^^^^^^^^^^
    executor.submit( () -> processRule(rule_queue.poll()));           
}

问题是 rule_queue.size() 在每次迭代中都是 re-evaluated。考虑初始队列大小为 2 的情况。

Iteration    i   rule_queue.size()   result
---------    -   -----------------   ------
    1        0           2           submit
    2        1           1           exit loop

所以只有一半的规则会被提交。你想要的是:

while(rule_queue.size() > 0) {
    executor.submit( () -> processRule(rule_queue.poll()));           
}

如果您在 IDE 调试器中单步执行代码,您会立即看到这一点。