2012-01-01 5 views
2

Я готовлю приложение, в котором один производитель создает несколько миллионов задач, которые затем обрабатываются настраиваемым количеством потребителей. Связь от производителя к потребителю (вероятно) будет основана на очереди.Java-производитель/потребитель, обнаруживающий конец обработки

Из потока, который запускает продюсер/создает задачи, какой метод я могу использовать для ожидания выполнения всех задач? Я бы предпочел не возобновлять периодический опрос, чтобы проверить, пуста ли моя очередь задач. В любом случае пустая очередь задачи не является гарантией завершения последних задач. Эти задачи могут быть относительно длительными, поэтому вполне возможно, что очередь пуста, пока потребительские потоки все еще успешно обрабатывают.

Rgds, Маартен

ответ

1

Вы хотите знать, где каждые задачи завершается. У меня была бы очередная очередь завершенных отчетов задач. (Один объект/сообщение за задание) Когда этот счетчик достигает числа созданных вами задач, они все завершены. В этом отчете задачи также могут быть указаны любые ошибки и временная информация для задачи.

+0

Хммм, интересная идея. Для этого потребуется дополнительный поток, который читает очередь отчетов. Этот поток отчетов может затем уведомлять поток производителя о каком-либо объекте монитора. –

+0

Нить производителя может прочитать эту очередь перед продолжением. –

1

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

Имея потоки, проверяйте глобальную логическую переменную (помеченную как изменчивую), чтобы потоки знали, что они должны останавливаться.

+0

Это говорит о том, что каждое задание отклонено, а не каждая задача выполнена. –

+0

Вот почему глобальная переменная, которую вы можете использовать, чтобы сообщить, что потоки останавливаются, а затем присоединяется к ним, - это предложение второго абзаца. –

2

Возможно, вам захочется взглянуть на пакет java.util.concurrent.

Структура исполнитель уже предоставляет средства для выполнения задач с помощью ThreadPool. Абстракция Future позволяет дождаться завершения задач.

Включение обоих вместе позволяет легко координировать выполнение, развязывать задачи, действия (потоки) и результаты.

Пример:

ExecutorService executorService = Executors.newFixedThreadPool(16); 

    List<Callable<Void>> tasks = null; 
    //TODO: fill tasks; 

    //dispatch 
    List<Future<Void>> results = executorService.invokeAll(tasks); 

    //Wait until all tasks have completed 
    for(Future<Void> result: results){ 
     result.get(); 
    } 

Edit: Alternative Version с помощью CountDownLatch

ExecutorService executorService = Executors.newFixedThreadPool(16); 

    final CountDownLatch latch; 

    List<Callable<Void>> tasks = null; 
    //TODO: fill tasks; 

    latch = new CountDownLatch(tasks.size()); 

    //dispatch 
    executorService.invokeAll(tasks); 

    //Wait until all tasks have completed 
    latch.await(); 

А внутри ваших задач:

Callable<Void> task = new Callable<Void>() 
    { 

     @Override 
     public Void call() throws Exception 
     { 
      // TODO: do your stuff 

      latch.countDown(); //<---- important part 
      return null; 
     } 
    }; 
+0

Да, уже планировал использовать Исполнителей. Однако, если я не буду понимать Фьючерсы, я не думаю, что смогу их использовать. У меня может быть несколько миллионов задач, что означало бы отслеживать несколько миллионов фьючерсов ** в памяти **. Не хочу этого делать ... –

+0

Вы также можете использовать 'CountDownLatch', я добавил еще один пример. –

+0

О, мне нравится идея CountDownLatch, за исключением того, что я не знаю количество заданий заранее, и я не могу сперва генерировать полный список задач, потому что он не поместился в доступную кучу JVM ... Есть ли какая-либо альтернатива CountDownLatch, в основном, какой-то контрольный счетчик ссылок, где я могу сделать «refcount ++» при добавлении задачи и «refcount--» при выполнении задачи? –

0

Вы можете использовать присоединиться() метод для каждого потока ..о том, что до тех пор, пока все нити не станут e ваш основной поток не закончится! И таким образом вы можете узнать, все ли потоки сделаны или нет!

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