Java主类在线程执行之前结束

时间:2012-04-18 00:20:11

标签: java multithreading

我有一个多线程执行,我想跟踪并打印执行时间,但是当我执行代码时,子线程比主执行花费的时间更长,因此输出不可见,也没有打印正确的值,因为它提前结束了。

以下是代码:

public static void main(String[] args) throws CorruptIndexException, IOException, LangDetectException, InterruptedException {

    /* Initialization */
    long startingTime = System.currentTimeMillis();
    Indexer main = new Indexer(); // this class extends Thread
    File file = new File(SITES_PATH);
    main.addFiles(file);

    /* Multithreading through ExecutorService */
    ExecutorService es = Executors.newFixedThreadPool(4);
    for (File f : main.queue) {
        Indexer ind = new Indexer(main.writer, main.identificatore, f);
        ind.join();
        es.submit(ind);
    }

    es.shutdown();

    /* log creation - code I want to execute when all the threads execution ended */
    long executionTime = System.currentTimeMillis()-startingTime;
    long minutes = TimeUnit.MILLISECONDS.toMinutes(executionTime);
    long seconds = TimeUnit.MILLISECONDS.toSeconds(executionTime)%60;
    String fileSize = sizeConversion(FileUtils.sizeOf(file));

    Object[] array = {fileSize,minutes,seconds};
    logger.info("{} indexed in {} minutes and {} seconds.",array);
}

我尝试了几个解决方案,例如join(),wait()和notifyAll(),但没有一个解决方案。

我在stackoverflow上找到了Q&A来处理我的问题,但是如果我把

放入了join()
  

es.awaitTermination(timeout,TimeUnit.SECONDS);

实际上,执行程序服务从不执行线程。

哪个可以是仅在ExecutorService块中执行多线程的解决方案,并在最后执行主执行?

2 个答案:

答案 0 :(得分:1)

ExecutorService#submit()方法返回一个Future对象,可用于等待提交的任务完成。

您的想法是收集所有这些Future,然后在每个get()上调用ExecutorService es = Executors.newFixedThreadPool(4); List<Future<?>> futures = new ArrayList<Future<?>>(); for (File f : main.queue) { Indexer ind = new Indexer(main.writer, main.identificatore, f); ind.join(); Future<?> future = es.submit(ind); futures.add(future); } // wait for all tasks to complete for (Future<?> f : futures) { f.get(); } // shutdown thread pool, carry on working in main thread... 。这可确保在主线程继续之前完成所有已提交的任务。

这样的事情:

{{1}}

答案 1 :(得分:1)

根据您的用户案例,您也可以使用invokeAll方法。来自Javadoc:

  

执行给定的任务,返回持有他们的期货清单   完成后的状态和结果。 Future.isDone()对每个都是正确的   返回列表的元素。请注意,已完成的任务可能具有   正常终止或通过抛出异常终止。结果   如果同时修改给定集合,则此方法未定义   此操作正在进行中。

使用:

final Collection<Indexer> tasks = new ArrayList<Indexer>();
for(final File f: main.queue) {
    tasks.add(new Indexer(main.writer, main.identificatore, f));
}

final ExecutorService es = Executors.newFixedThreadPool(4);
final List<Future<Object>> results = es.invokeAll(tasks);

这将执行所有提供的任务并等待它们完成处理,然后继续主线程。您需要调整代码以满足您的特定需求,但您可以获得要点。快速说明,有invokeAll方法的变体接受超时参数。如果要在继续之前等待最长时间,请使用该变体。并确保在invokeAll完成后检查收集的结果,以验证已完成任务的状态。

祝你好运。