Java线程中的RejectedExecutionException

7

我正在使用Java编写一个多线程程序。我已经写了以下代码:

exec.execute(p)  // where p is a runnable task working on an array
print array
exec.shutdown

我面临的问题是,数组打印出了正确的输出,但是随后出现了被拒绝的执行异常错误。 我不明白为什么当线程处理并给出正确输出后,为什么会出现这个错误...

1
当任务无法被接受执行时,会抛出RejectedExecutionException异常。可能是控制流程中存在简单错误,建议您展示一些代码以便我们检查。 - Carl Smotricz
你正在使用哪个特定的Executor实现呢? - Carl Smotricz
4个回答

12

我认为你关闭了执行器得太早。这是一个例子,我认为你应该这样工作。

public class Main {
    public static void main(String[] args) throws Exception {

        // the array to modify
        final int[] array = new int[1000];

        // start the executor (that modifies the array)
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 1000; i++) {
            final int c = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    array[c] = c;
                }
            });
        }

        // wait for all tasks to quit
        executor.shutdown();
        while (!executor.awaitTermination(10, TimeUnit.SECONDS)); 

        // print the array
        System.out.println(Arrays.toString(array));
    }
}

还要注意,同时在同一个数组上工作可能会导致不一致性 - 你必须非常确定你没有对依赖于该数组的数组进行操作。


3
ExecutorService.shutdown()并不会等待任务完成关闭,它只是告诉ExecutorService不再接收任何新任务并终止。在调用shutdown()后应该调用ExecutorService.awaitTermination()来阻塞调用线程,直到任务完成。 - Rich
我认为while循环不必要,因为“executor.awaitTermination”会自行阻塞。 - JoachimR
@IHeartAndroid 如果在超时时间内没有完成所有任务(阻塞10秒钟),那么这是必要的... 在这个小例子中很不可能,但是这是正确的。 - dacwe

6
问题在于即使调用了shutdown(),您仍然会提交新任务。因此使用executor.awaitTermination()也无法解决此问题。
为解决该问题,请在提交任务时检查执行器是否已关闭。
例如:
if (!executor.isShutdown())
{
  executor.execute(new Runnable() {
                         @Override
                         public void run() {
                              array[c] = c;
                         }
                  });
}

希望这有所帮助...(这是需要翻译的内容)

在我的情况下,执行者恰好在 if 和 execute 行之间关闭。因此,如果涉及并发,则需要将 execute() 和 shutdown() 调用放在同步块/方法中。 - Algorithm and Blues

2

我曾经在运行时shutdown hook中关闭创建的执行器(executors)

Runtime.getRuntime().addShutdownHook(new Thread() {

            public void run() {
            if(!eExecutor.isShutdown()) {
                eExecutor.shutdown();
                // await termination code
              }
            }

        });

0

另一个选项是在提交给执行器时获取未来,然后通过调用get在未来上阻塞


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接