Хорошая стратегия - обработка множества потоков, запись одного потока и очередь сообщений между ними. Вопрос, который просто нужно решить, это знать, когда вся работа закончена. Один из способов сделать это - подсчитать, сколько рабочих потоков вы запустили, а затем подсчитать, сколько ответов вы получили. Примерно такой псевдокод:
int workers = 0
for each work item {
workers++
start the item's worker in a separate thread
}
while workers > 0 {
take worker's response from a queue
write response to file
workers--
}
Этот подход также работает, если рабочие могут находить больше рабочих элементов во время выполнения. Просто включите любую дополнительную еще не обработанную работу в ответы рабочих, а затем увеличьте число рабочих и запустите рабочие потоки, как обычно.
Если каждый из работников возвращает только одно сообщение, вы можете использовать Java ExecutorService для выполнения экземпляров Callable, которые возвращают результат. Методы ExecutorService предоставляют доступ к экземплярам Future, из которых вы можете получить результат, когда Callable завершит свою работу.
Таким образом, вы должны сначала отправить все задачи в ExecutorService, а затем перебрать все фьючерсы и получить их ответы. Таким образом, вы будете писать ответы в том порядке, в котором вы проверяете фьючерсы, которые могут отличаться от порядка, в котором они заканчивают свою работу. Если задержка не важна, это не должно быть проблемой. В противном случае очередь сообщений (как упомянуто выше) может быть более подходящей.