Сохранение итогов каждого потока Spring Batch

Я реализую пакетное приложение Spring, которое выполняет некоторые обновления базы данных. Здесь нет файлов ввода/вывода, только прямые обновления базы данных.

Программа выложена так:

  1. Подготовительный тасклет вызывает процедуру БД, чтобы получить все параметры задания и работу, которую необходимо выполнить.
  2. работа отправляется в разделитель, где работа делится на потоки
  3. Тасклет вызова запускается и вызывает в каждом потоке вызов другой процедуры, которая выполняет фактические обновления в базе данных.
  4. После того, как все потоки завершены, вызывается процедура «конец», чтобы закрыть любую регистрацию БД.

Моя проблема находится между шагами 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));

    }
}

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

Спасибо за любую помощь в этом!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В соответствии с вашей настройкой ваш тасклет будет совместно использоваться несколькими потоками, поэтому он должен быть потокобезопасным.

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, и она отлично работает для того, что мне нужно. Теперь переменная обновляется должным образом. Еще раз спасибо за то, что указали мне правильное направление.

ACCFAN 11.04.2019 16:03

Здорово! Рад помочь.

Mahmoud Ben Hassine 11.04.2019 16:50

Другие вопросы по теме