Я пытаюсь использовать потоки Java для параллельной обработки списка клиентов. Это краткосрочная помощь в решении проблемы, которую мы решаем в рамках перестройки всей нашей системы.
Я начинаю с структуры List<Customer> Customers
, которая содержит контактную информацию клиента и все соответствующие данные транзакции. Концептуально код, который я заменяю, выглядит следующим образом:
long emailsSent = 0;
List<Customer> customers = methodLoadingAllrelevantData();
for (Customer customer: customers) {
boolean isEmailSent = sendEmail(customer);
if (isEmailSent) {
emailsSent++;
}
}
Функция sendMail(customer)
:
- Определяет, следует ли отправлять электронное письмо
- Форматирует электронную почту
- Попытки отправить письмо
- Возвращает истину, если электронное письмо было успешно отправлено
Не очень хороший код, но я просто пытаюсь добиться большей скорости от существующего кода, не пытаясь сделать его лучше. Метод и все его вызовы на 100 процентов безопасны для потоков.
Я поместил его в следующую структуру потока:
ForkJoinPool limitedParallelThreadPool = new ForkJoinPool(numberOfThreads);
emailsSent = limitedParallelThreadPool.submit( () ->
customers.stream().parallel()
.map(this::_emailCustomer)
.filter(b -> b == true).count()
).get();
Это работает должным образом, возвращая те же данные, что и последовательная версия.
Мои вопросы: поскольку цель моего метода состоит в том, чтобы сгенерировать электронное письмо, неужели я плохо использую функцию map
? Есть ли лучший ответ? По сути, я сопоставляю Customer с логическим значением, но часть этого сопоставления требует, чтобы процесс вызывал электронную почту.
Изначально я пытался использовать оператор forEach()
, но я не мог понять, как получить счетчик, не добавляя информацию о состоянии в функцию sendMail
, которая мешает его поточнобезопасности.