Я реализую пакетное приложение Spring, которое выполняет некоторые обновления базы данных. Здесь нет файлов ввода/вывода, только прямые обновления базы данных.
Программа выложена так:
Моя проблема находится между шагами 3 и 4. После того, как каждый поток выполнен, он собирает выходные параметры процедуры, один из которых - сколько работы было фактически обновлено. Я хочу иметь возможность вести подсчет всех потоков и того, сколько работы было проделано всеми. Затем эта информация будет передана на шаг 4, который включит эти итоги в таблицы регистрации БД.
В настоящее время я добавляю любой результат процедуры на шаге 3 в Map<String, String> resultMap
и вижу общее количество каждого потока. Моя проблема заключается в том, как передать ВСЕ потоки на шаг 4.
Я попытался объявить пару переменных в верхней части тасклета вызова, которые будут использоваться для сохранения текущей суммы. Проблема в том, что их значения сбрасываются после каждого потока, хотя я использую +=
при назначении значений из карты.
public class SpringBatchInvocationTasklet implements Tasklet, StepExecutionListener {
int totalWork = 0;
int totalWorkProcessed = 0;
@Override
public RepeatStatus execute(StepContribution arg0, ChunkContext chunkContext) throws Exception {
Map<String, String> resultMap = SpringBatchDAO.process(workList, dbLogId, commitVal, userName, threadNo);
totalWork += Integer.parseInt(resultMap.get(SpringBatchConstants.TOTAL_WORK));
totalWorkProcessed += Integer.parseInt(resultMap.get(SpringBatchConstants.TOTAL_WORK_PROCESSED));
}
}
Подводя итог, мне нужно иметь возможность получить текущую сумму всех потоков для той работы, которую они все сделали, и передать ее в конечный процесс.
Спасибо за любую помощь в этом!
В соответствии с вашей настройкой ваш тасклет будет совместно использоваться несколькими потоками, поэтому он должен быть потокобезопасным.
The problem is their values are reset after each thread even though I'm using += when assigning the values from the Map
Оператор +=
не является потокобезопасным, так как это не атомарная операция. Вам нужно использовать синхронизацию/блокировки вокруг вашего кода или использовать поточно-безопасную реализацию карты (например, ConcurrentHashMap
) и AtomicInteger
(см. метод incrementAndGet
) вместо int
для ваших переменных totalWork
и totalWorkProcessed
.
Могут помочь следующие вопросы/ответы: Является ли оператор += потокобезопасным в Java?
Надеюсь это поможет.
Здорово! Рад помочь.
Большое спасибо Махмуду. Это была именно проблема, но я не был на 100%. В итоге я использовал версию этого ответа stackoverflow.com/a/29884069/7829505, и она отлично работает для того, что мне нужно. Теперь переменная обновляется должным образом. Еще раз спасибо за то, что указали мне правильное направление.