Как дождаться завершения потоков, порожденных весенним планировщиком?

Я использую spring-scheduler и создаю несколько потоков из метода @Scheduled (один из них имеет вызов отдыха). Как лучше всего подождать в @Scheduled методе завершения всех потоков, а затем выйти?

Сведения о приложении: у меня есть запланированная задача, в которой я получаю список объектов одного типа (скажем, порядок классов) из БД, делю их на части (поэтому, если я получу 5000 заказов, я разделю их на 5 куски по 1000 штук). Затем я перебираю каждый фрагмент и для каждого заказа в фрагменте я получаю список продуктов из Order, а затем перебираю их. Для каждого продукта мне нужно сделать вызов другой службы, которая возвращает значение (например, цену), которое мне нужно установить в этом продукте. Это планируется делать каждые 1 час (настраивается).

Что я до сих пор думал: в планировщике вызовите UpdatePriceJobs метод execute. Этот метод сначала делит список на части. Затем каждый фрагмент обрабатывается ChunkProcessor своим методом обработки. Метод процесса аннотируется spring @Async, поэтому каждый фрагмент обрабатывается в отдельном потоке. Затем он вызывает метод процесса службы productProcessor, который выполняет остальные вызовы. Этот метод снова помечен знаком @Async. Идея состоит в том, чтобы запустить Chunks параллельно, а затем сделать параллельные вызовы обновления цен. Как видите, мне придется дождаться завершения всех потоков, иначе некоторые продукты не получат обновленные цены.

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

@Override
public void process(Chunk<Order> chunk) {
    final List<Chunk<Order>> chunks = orderChunkProvider.getChunks(items);
    for (final Chunk<Order> chunk : chunks) {
        OrderChunkProcessor.process(chunk);
    }

}

@Async
@Override
public void process(Chunk<Order> chunk) {
    final List<Order> orders = chunk.getItems();
    for (final Order order : orders ) {
        final List<Product> products = order.getProductss();
        for (final Product product : products ) {
            productProcessor.process(product);
        }
 }

productProcessor.process(product) метод выполняет остальной вызов и также аннотируется @Async

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

PS: Я не могу использовать spring -batch, поскольку мы используем базу данных NoSql, которая не поддерживает транзакции, а spring -batch не поддерживает это.


person humbleCoder    schedule 22.01.2019    source источник


Ответы (1)


Попробуйте Fork/Join framework в java .Fork/Join - это среда параллельной обработки. Во-первых, вы можете установить только параллельный уровень, не нужно выяснять, сколько потоков вам нужно. Во-вторых, метод ia awaitTermination может блокировать текущий поток до завершения процесса, поэтому вам не нужно использовать CountDownLatch. Если вы решите использовать Fork/Join, эта статья может вам помочь.

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

person TongChen    schedule 22.01.2019
comment
У ForkJoinPool много проблем: coopsoft.com/ar/CalamityArticle.html - person humbleCoder; 22.01.2019
comment
Если вы не используете другие профессиональные библиотеки, я считаю, что использование Fork / join - хороший выбор, вы можете попробовать справиться с этой задачей. - person TongChen; 22.01.2019