ExecuterService停止处理两个中的一个线程

时间:2017-05-22 10:33:32

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

  1. 我有一个需要在for循环中处理的40000条记录的列表。由于我有一个双处理器系统。我创建了一个这样的fixedThreadPool:

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

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

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

  4. 这是我的问题:

    我写了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;
    

1 个答案:

答案 0 :(得分: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等等,你的&#34;处理你的输入&#34;然后代码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(...)的线程。