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

Java主类在线程执行之前结束,java,multithreading,Java,Multithreading,我有一个多线程执行,我想跟踪并打印执行时间,但当我执行代码时,子线程比主执行时间长,因此输出不可见,也不会打印正确的值,因为它会提前终止 代码如下: public static void main(String[] args) throws CorruptIndexException, IOException, LangDetectException, InterruptedException { /* Initialization */ long startingTime =

我有一个多线程执行,我想跟踪并打印执行时间,但当我执行代码时,子线程比主执行时间长,因此输出不可见,也不会打印正确的值,因为它会提前终止

代码如下:

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上发现了这一点,它解决了我的问题,但是join()被忽略,如果我

等待终止(超时,时间单位为秒)

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

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

方法返回一个
未来的
对象,该对象可用于等待提交的任务完成

其思想是收集所有这些
Future
s,然后对它们中的每一个调用
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...
Executors服务=Executors.newFixedThreadPool(4);
列表>();
for(文件f:main.queue){
索引器ind=新索引器(main.writer,main.identificatore,f);
ind.join();
未来=提交(ind);
期货。添加(期货);
}
//等待所有任务完成
for(未来f:未来){
f、 get();
}
//关闭线程池,在主线程中继续工作。。。

根据您的用户情况,您最好使用
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);
final Collection tasks=new ArrayList();
for(最终文件f:main.queue){
添加(新索引器(main.writer,main.identificatore,f));
}
final Executors服务es=Executors.newFixedThreadPool(4);
最终列表结果=es.invokeAll(任务);
这将执行所有提供的任务,并等待它们完成处理,然后再继续主线程。您需要调整代码以满足您的特殊需要,但您得到了要点。请注意,
invokeAll
方法的一个变体接受超时参数。如果要在继续之前等待最长时间,请使用该变量。并确保在
invokeAll
完成后检查收集的结果,以验证已完成任务的状态


祝你好运。

我只需将
Runnable
提交给
ExecutorService
,而不调用
join()
或其他任何东西。您使用并发框架的方式似乎不正确。还要注意生成的线程是用户线程:守护进程线程不会阻止JVM退出。但是,我非常确定默认情况下线程是用户线程。