2012-04-18 4 views
0

У меня многопоточное выполнение, и я хочу отслеживать и распечатывать время выполнения, но когда я выполняю код, дочерние потоки занимают больше времени, чем основное выполнение, поэтому вывод не является видимый и не печатает правильное значение, так как оно заканчивается раньше.Главный класс Java заканчивается до выполнения нитей

Вот код:

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); 
} 

Я попробовал несколько решений, таких как присоединиться(), ждать() и notifyAll(), но ни один из них не работал.

Я нашел этот Q&A на StackOverflow, который рассматривает мою проблему, но присоединиться() игнорируется, и если я ставлю

es.awaitTermination (тайм-аут, TimeUnit.SECONDS);

Фактически служба-исполнитель никогда не выполняет потоки.

Какой может быть решение для выполнения многопоточности только в блоке ExecutorService и завершение основного исполнения в конце?

+0

Я бы просто отправил 'Runnable' в' ExecutorService' и не называет 'join()' или что-то еще. То, как вы используете структуру параллелизма, выглядит некорректно.Также следите за тем, что порожденная нить является пользовательским потоком: потоки демона не остановят JVM от выхода. Я уверен, что потоки по умолчанию - это потоки пользователей. –

ответ

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, чтобы проверить статус выполненных задач.

Удачи.

1

Метод ExecutorService#submit() возвращает объект Future, который может использоваться для ожидания, пока заданная задача не будет завершена.

Идея состоит в том, что вы собираете все эти 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... 
+0

Большое спасибо! Теперь он работает хорошо! – Tsuneo

Смежные вопросы