0

主要流程:

            int cpus = Runtime.getRuntime().availableProcessors();
            ExecutorService executor = Executors.newFixedThreadPool(cpus);
            List<Callable<Object>> todo = new ArrayList<Callable<Object>>(lines.size());
            for (int r = 0; r < lines.size(); r++) {
                String filename = r + 1 + "";
                todo.add(Executors.callable(new AppConsole(filename, lines.get(r))));
            }
            List<Future<Object>> answers = executor.invokeAll(todo);

AppConsole类实现了Runnable,重写的run方法如下:

public void run() {
  try{



  } catch (SecurityException exception) {
            exception.printStackTrace();
        } catch (FileNotFoundException exception) {
            exception.printStackTrace();
        } catch (IOException exception) {
            exception.printStackTrace();
        } catch (SAXException exception) {
            exception.printStackTrace();
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            if (output != null) {
                output.close();
            }
        }
  }

}

由于其中一个线程引发了连接超时异常,主进程被挂起并且无法完成。现在我可以看到 CPU 使用率下降到 0%,并且在暂停时内存消耗保持在同一水平。

有人可以帮我解决这个问题吗?至少,帮我完成主要过程?

4

3 回答 3

3

抛出异常可以释放任务和主线程。ExecutorService 将异常抛出视为另一个返回值,并且在处理它时没有问题。

主线程只会阻塞等待您的一项任务完成。我会查看仍然处于活动状态的任务/线程,看看它们在做什么,例如它们可能还没有超时。

于 2013-08-06T08:39:18.027 回答
0

您只需要添加:

executor.shutdown();

这会等待所有任务完成并关闭所有线程,然后应用程序将退出。请参阅 javadoc 了解newFixedThreadPool

创建一个线程池,该线程池重用在共享无界队列上运行的固定数量的线程。在任何时候,最多 nThreads 个线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,它们将在队列中等待,直到有线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,新的线程将取代它。池中的线程将一直存在,直到显式关闭。

于 2013-08-06T08:49:19.037 回答
0

您可以使用带有显式超时值的 invokeAll 的替代版本:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

invokeAll(Collection<? extends Callable<T>> tasks,
                          long timeout,
                          TimeUnit unit)

这样,您可以强制所有任务在 30 秒后超时。然后您可以检查返回的 Futures 以查看哪些已完成。

于 2013-08-06T08:49:51.620 回答