Java execuetorService 运行 太快了?

Java execuetorService running too fast?

通过以下代码

    ExecutorService executorService = Executors.newFixedThreadPool(3)
    for (int i=0; i<10; i++){
            executorService.execute(new Runnable() {
                @Override
                void run() {
                    try {
                        Thread.sleep(1*1000)
                        System.out.println("Thread " + Thread.currentThread().getName() + " processing item " + i)
                    } catch (InterruptedException e) {
                        e.printStackTrace()
                    }
                }
            })
    }

我期望输出如下:

线程池-1-线程2处理项目1

线程池-1-线程3处理项目2

线程池-1-线程2处理项目3

线程池-1-线程3处理项目4

线程池-1-线程2处理项目5

线程池-1-线程2处理项目7

线程池-1-线程3处理项目6

线程池-1-线程2处理项目8

线程池-1-线程3处理项目9

线程池-1-thread-1处理项目0

但结果是:

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-thread-1处理项目10

线程池-1-线程2处理项目10

线程池-1-线程3处理项目10

正确的输出是在 executorService.exeute 方法之前添加一个临时变量。问题来了,出现意外输出的原因是什么?

  • 首先你的代码不会编译(至少在 Java 中不会,可能会在 Groovy 中编译)
  • 'i' 不能在块内使用,因为它不是最终的,也不能是最终的,因为它在 for 循环中使用。

"The correct out put is by adding a temp variable before the executorService.exeute method."是什么意思?

此外,您不应该期待该输出。你不能保证这样的顺序,例如我得到:

Thread pool-1-thread-1 processing item 0 Thread pool-1-thread-2 processing item 1 Thread pool-1-thread-3 processing item 2 Thread pool-1-thread-3 processing item 5 Thread pool-1-thread-1 processing item 3 Thread pool-1-thread-2 processing item 4 Thread pool-1-thread-1 processing item 7 Thread pool-1-thread-2 processing item 8 Thread pool-1-thread-3 processing item 6 Thread pool-1-thread-1 processing item 9

通过使用此代码:

    ExecutorService executorService = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 10; i++) {
        final int j = i;
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1 * 1000);
                    System.out.println("Thread "
                            + Thread.currentThread().getName()
                            + " processing item " + j);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

您的所有 运行nables 共享 i 的同一个实例。

到他们 运行 时,此变量的值为 10

因此输出。

如果您使用闭包,每个 运行nable 将获得 i 的一个新实例,您将获得预期的输出:

ExecutorService executorService = Executors.newFixedThreadPool(3)
10.times { i ->
   executorService.execute { ->
       Thread.sleep(1000)
       println "Thread ${Thread.currentThread().getName()} processing item $i"
   }
}
executorService.shutdown()

但它们不会按照您预期的顺序排列,因为线程...