Java execuetorService运行得太快了?

时间:2017-07-06 06:36:37

标签: groovy executorservice

通过以下代码

    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-线程-1处理项目0

但事实证明是:

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

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

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

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

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

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

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

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

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

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

正确的输出是在executorService.exeute方法之前添加临时变量。这就是问题,是什么导致意外输出?

2 个答案:

答案 0 :(得分:1)

  • 首先关闭你的代码将不会编译(至少不是在Java中,可能会在Groovy中这样做)
  • 'i'不能在块中使用,因为它不是最终的,因为它在for循环中使用,所以它不能是最终的。

你是什么意思“正确的输出是通过在executorService.exeute方法之前添加一个临时变量。”

另外,你不应该期待那个输出。你无法保证这样的订单,例如我得到了:

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();
                }
            }
        });
    }
}

答案 1 :(得分:0)

所有runnables共享i的同一个实例。

当它们运行时,此变量的值为10

因此输出。

如果你使用一个闭包,每个runnable将获得一个i的新实例,你将获得预期的输出:

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

但是他们不会按照你所说的顺序,因为线程......