У меня есть какая-то таблица базы данных, и мне нужно обрабатывать записи из нее 5 одновременно, пока приложение работает. Итак, это выглядит так:
- Получить запись, которая еще не была обработана или не обрабатывается другими потоками.
- Обработайте его (это длительный процесс, который зависит от подключения к Интернету, поэтому он может тайм-аут / выбрасывать ошибки).
- Перейти к следующей записи. Когда достигнут конец таблицы, начинайте с начала.
У меня нет большого опыта работы с потоками, поэтому я вижу две возможные стратегии:
Подход А.
1. Создать новый ExecutorService:
ExecutorService taskExecutor = Executors.newFixedThreadPool(5);
2.Добавить к нему 5 заданий:
for (int i = 0; i < 5; i++) {
taskExecutor.execute(new MyTask());
}
3.Каждое задание будет бесконечным циклом, который: читает запись из таблицы, обрабатывает ее, а затем получает другую запись.
Проблема этого подхода заключается в том, как сообщить другим потокам о том, какие записи обрабатываются в данный момент. Для этого я могу либо использовать поле «status» в таблице, либо просто использовать некоторый CopyOnWriteArraySet, в котором хранятся идентификаторы, обрабатываемые в данный момент.
Подход B.
1.Создать тот же ExecutorService:
ExecutorService taskExecutor = Executors.newFixedThreadPool(5);
2. Иметь бесконечный цикл, который выбирает записи, которые необходимо обработать, и передает их исполнителю:
while (true) {
//get next record here
taskExecutor.execute(new MyTask(record));
//monitor the queue and wait until some thread is done processing,
//so I can add another record
}
3.Каждое задание обрабатывает одну запись.
Проблема этого подхода заключается в том, что мне нужно добавлять задачи в очередь исполнителя медленнее, чем они обрабатываются, чтобы не допустить их накапливания со временем. Это означает, что мне нужно следить не только за тем, какие задачи выполняются в данный момент, но и когда они завершаются, поэтому я могу добавлять новые записи в очередь.
Лично я думаю, что первый подход лучше (легче), но я чувствую, что второй подход более правильный. Как вы думаете? Или, может быть, я должен сделать что-то совершенно другое?
Также я могу использовать библиотеки Spring или Quartz для этого при необходимости.
Спасибо.