【问题标题】:ExecuterService stopped processing one thread out of twoExecutorService 停止处理两个线程中的一个
【发布时间】:2017-05-22 10:33:32
【问题描述】:
  1. 我有一个需要在 for 循环中处理的 40000 条记录的列表。因为我有两个处理器系统。我创建了一个这样的固定线程池:

    int threads = Runtime.getRuntime().availableProcessors(); ExecutorService service = Executors.newFixedThreadPool(threads);

  2. 并将我的ArrayList 分成两个子列表。对于每个子列表,我创建了一个Callable,它执行相同的功能(涉及迭代子列表并进行一些处理)并返回一个Future 对象。

  3. 我使用executorServiceObject.submit(callable) 提交了这两个Callable,并将返回的Future 对象添加到我的Future 对象列表中

这是我的问题:

我写了System.Out.printLn("Processed Item" +item.id) // consider item as the name of reference variable for current iteration

一段时间以来一切都很好,我可以看到两个线程同时工作。但一段时间后,其中一个线程已停止处理。只有一个线程在运行。 (我知道这一点是因为我可以在控制台上看到不再打印给线程 2 的 id)。

有人知道这是怎么回事吗?我的意思是为什么 ExecutorService 停止运行第二个线程。

提前感谢您的帮助。

按照我之前应该做的那样添加示例代码:

public List<Output> processInputs(List<Input> inputs)
        throws InterruptedException, ExecutionException {

    int threads = Runtime.getRuntime().availableProcessors();
    ExecutorService service = Executors.newFixedThreadPool(threads);

    List<Future<Output>> futures = new ArrayList<Future<Output>>();
    for (final Input input : inputs) {
        Callable<Output> callable = new Callable<Output>() {
            public Output call() throws Exception {
                Output output = new Output();
                // process your input here and compute the output
                return output;
            }
        };
        futures.add(service.submit(callable));
    }

    service.shutdown();

    List<Output> outputs = new ArrayList<Output>();
    for (Future<Output> future : futures) {
        outputs.add(future.get());
    }
    return outputs;

【问题讨论】:

  • edit您的问题包含您程序中的相关代码。理想情况下,您应该包含一个重现问题的minimal reproducible example
  • 这可能实际上并没有停止。它可能处于等待状态。检查非工作线程的run方法,看看最后执行的是哪一行。
  • @pikrut 我使用了 'Callable' 所以没有 run() 方法。其次,Callable 是在 for 循环中创建的(1 个可调用的 1 个子列表)。这意味着两个子列表的调用方法实现相同
  • @Kenster:对不起,我现在添加了示例代码。我在我的代码中提到了一条评论,这意味着我正在迭代我的子列表并进行一些处理。

标签: java multithreading concurrency executorservice java.util.concurrent


【解决方案1】:

一段时间以来一切都很好,我可以看到两个线程同时工作。但一段时间后,其中一个线程已停止处理。只有一个线程在运行。 (我知道这一点是因为我可以在控制台上看到分配给线程 2 的 id 不再被打印)。

我怀疑您的处理线程抛出了异常。 Future.get() 方法可以抛出 ExecutionException "if the computation threw an exception"

// the following might throw an exception if the background job threw
outputs.add(future.get());

如果您的“处理您的输入”代码引发了 NPE、IOException 等,则该异常由 Callable 引发并存储在 Future 中,因此它可以由 get() 引发方法,但包装在 ExecutionException 中。这很有用,因此等待的线程可以获取并处理(记录等)后台线程抛出的异常。

除了让您的 processInputs(...) 方法将异常抛出给可能会丢失的调用者之外,我会在您的 while 循环中执行以下操作:

try {
   outputs.add(future.get());
} catch (InterruptedException ie) {
   // always a good pattern if the thread that is waiting was interrupted
   Thread.currentThread().interrupt();
   return;
} catch (ExecutionException ee) {
   // somehow log the error
   logger.error("Computation failed to process", ee);
   // now continue and get the next future in the list
}

如果您没有捕获并正确处理该ExecutionException,那么处理异常也会终止调用processInputs(...) 的线程。

【讨论】:

  • 你说得对,我在 get() 方法上遇到了 ExecutionException。我已经捕获了这两个异常,并且正在控制台上打印堆栈跟踪。重新处理线程1的数据并得到输出有意义吗?还是我应该重新运行程序并查看是否再次抛出异常?我的意思是在这种情况下,我可以做些什么比在我的代码中记录错误更好吗?
  • 不确定@Aman。这取决于你在做什么。如果您的处理方法可能会再次起作用,那么请确保您可以再试一次。我认为您需要了解为什么会发生异常以及重试是否有意义。
  • 好的,我会检查的。谢谢你的解释,我接受你的回答。我收到此异常:java.util.concurrent.ExecutionException: <938587 nonfatal store error>
猜你喜欢
  • 2021-11-09
  • 2015-07-18
  • 2016-08-31
  • 2021-10-23
  • 2011-08-22
  • 1970-01-01
  • 2023-03-07
  • 2019-01-26
  • 1970-01-01
相关资源
最近更新 更多