如何正确地多线程集合独立任务?

时间:2012-08-08 09:34:08

标签: java multithreading

我正在使用此代码在不同的CPU核心之间划分几百个任务。

    final List<Throwable> errors = Collections.synchronizedList(Lists.<Throwable>newArrayList());

    final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    for (...) {

        pool.execute(new Runnable() { @Override public void run() {

            try {

                // TASK HERE

            } catch (Throwable e) {
                errors.add(e);
            }

        }});

    }

    pool.shutdown();
    try {
        pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    if (!errors.isEmpty()) throw Exceptions.wrap(errors.get(0)); // TODO multi-exception

它有效,但不太好。

  • 没有超时的awaitTermination版本,这就是我想要的。
  • 我需要自己收集错误。

这样做的正确/常用方法是什么?

3 个答案:

答案 0 :(得分:3)

线程池的重点是重用线程。您应该在应用程序启动时创建它,在创建任务的代码之外创建它并注入它。添加任务后无需关闭池。您在应用程序关闭时执行此操作。

要运行任务集合,请使用ExecutorService.invokeAll。要在之后获得结果,请在每个返回的get上调用Futures。它将重新抛出任务抛出的任何异常,因此您可以在之后收集它。

答案 1 :(得分:1)

您可以使用future来执行错误处理:

final List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < 5; i++) {

    futures.add(pool.submit(new Runnable() { @Override public void run() {
            // TASK HERE
    }}));

}

for (Future f : futures) {
    try {
        f.get();
    } catch (ExecutionException e) {
        //something bad happened in your runnable
    }
}

//when you are done with the executor

pool.shutdown();
try {
    pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

答案 2 :(得分:0)

我认为您需要提交每个Runnable,然后返回Future,然后在每个Future上调用get()

当您致电get()时,您将获得Runnable的结果或遇到的异常。