лямбда-foreach функция ParallelsStream создает меньше данных, чем ожидалось - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь реализовать лямбда-foreach параллельный поток массива для повышения производительности существующего приложения.

До сих пор итерация foreach без параллельного потока создает ожидаемый объем данных, записанных в базу данных.

Но когда я переключаюсь на параллельный поток , он всегда записывает меньше строк в базу данных.Скажем, из 10.000 ожидаемых, почти 7000 строк, но результат здесь разный.

Есть идеи, что мне здесь не хватает, условия гонки данных или я должен работать с блокировками и синхронизироваться?

Кодделает что-то вроде этого в основном:

// Create Persons from an arraylist of data

arrayList.parallelStream()
          .filter(d -> d.personShouldBeCreated())
          .forEach(d -> {

   // Create a Person
   // Fill it's properties
   // Update object, what writes it into a DB

  }
);

То, что я пробовал до сих пор

Соберите результат в новый список с помощью ...

collect(Collectors.toList())

... и затем перебираем новый список и выполняем логику, описанную в первом фрагменте кода.Размер нового «собранного» * ​​1027 * ArrayList совпадает с ожидаемым результатом, но в конце все еще меньше данных, созданных в базе данных.

Обновление / Решение:

Основываясь на ответе, который я пометил (а также намеки в комментариях) касающемся не поточно-безопасных частей в этом коде, я реализовал его следующим образом, что в итоге дает мнеожидаемое количество данных.Производительность повысилась, сейчас требуется только 1/3 реализации.

StringBuffer sb = new StringBuffer();
arrayList()
  .parallelStream()
  .filter(d-> d.toBeCreated())
  .forEach(d ->
    sb.append(
            // Build an application specific XML for inserting or importing data
    )
  );

Специфической частью приложения является API для импорта данных на основе XML, но я думаю, что это можно сделать с помощью простых вставок JDBC SQL.

1 Ответ

0 голосов
/ 29 января 2019

Скорее всего, ваш код в лямбда-выражении не является поточно-ориентированным, потому что в коде используются общие не параллельные структуры данных или их манипулирование требует блокировки

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

Возможно, вы могли бы получить некоторые преимущества в плане параллельного составления содержимого файла массовой вставки, но этобудет зависеть от того, как массовая вставка может быть реализована через API вашей базы данных ... нужно ли сначала выгружать ее в текстовый файл?в этом случае ваш параллельный поток может составлять различные строки этого текста параллельно и, наконец, объединить их в текстовый файл для загрузки в БД.Возможно, вместо текстового файла он позволяет вам использовать коллекцию / список объектов операторов в памяти, в этом случае ваш параллельный поток может создавать эти объекты параллельно и собирать их в окончательный набор / список для массовой вставки в вашу БД..

...