Экземпляры Phaser и Spring MVC

#java #multithreading #spring #phaser

#java #многопоточность #весна #phaser

Вопрос:

У меня есть spring @Controller, который имеет сопоставление запросов. Когда на него отправляются запросы, он создает отложенный результат и запускает метод в классе делегатора.

В контроллере:

 @ResponseBody
@RequestMapping(MenuModelCodes.MENU_NAME)
DeferredResult<HttpEntity<?>> getModelCodesWithClass(String target) {
    final DeferredResult<HttpEntity<?>> deferredResult = getNewDeferredResult();
    delegator.doStuff(target);
    return deferredResu<
}
  

Метод doStuff в делегаторе имеет аннотацию @Async, поэтому он выполняется в другом потоке.
В этом потоке создается новый Phaser для отслеживания дочерних потоков, которые он создаст.
Сам поток делегатора регистрируется в phaser и запускает вызов метода в «AnotherClass», который также имеет аннотацию @Async. Т.Е. делегатор теперь порождает дочерние элементы.

Делегатор:

 public class Delegator {

    @Async
    public Object doStuff(String requestURI)  {

        Phaser phaser = new Phaser();
        phaser.register();
        Object result = anotherClass.createThreadDoWork(phaser);
        phaser.arriveAndDeregister();

        //Wait until phaser is completed
        while (!phaser.isTerminated()) {}

        return resu<
    }
}
  

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

Другой класс:

 public class AnotherClass {
    @Async
    public void createThreadDoWork(Phaser phaser) throws Throwable {        
        phaser.register();
        //some kind of logic / rest call etc.
        phaser.arriveAndDeregister();
    }
}
  

Когда все дочерние потоки завершатся, делегатор, который находится в этом фрагменте кода:

 while (!phaser.isTerminated()) {}
  

Будет продолжено, установите его отложенный результат, и поток делегатора завершится.

Итак, вот вопрос (ы):

Мне нужен фазер для каждого запроса — т. Е. Я создаю новый Phaser() каждый раз, когда запрос создает новый поток делегатора.

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

Можно ли использовать фазеры таким образом? Я делаю что-то не так? Я подумал, что это было бы полезным способом отслеживать завершение дочерних потоков и ждать их завершения?

Спасибо.

Ответ №1:

Можно ли использовать фазеры таким образом?

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


Я делаю что-то не так?

ДА. Не делай этого

 while (!phaser.isTerminated()) {}
  

Напряженное вращение убьет вас. Вместо этого сделайте:

 phaser.awaitAdvance();
  

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

Кроме того, если вы продвигаете фазер, где у вас есть несколько фаз, вам придется пересмотреть использование фазера.


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

Если у вас действительно создается несколько неизвестных потоков, было бы полезно использовать фазер.

Комментарии:

1. Спасибо, я удалил phaser.register() в делегаторе и просто поставил phaser.arriveAndAwaitAdvance() после вызова AnotherClass.createThreadDoWork(phaser), и все в порядке. Но это нормально только для одного вызова. Как только поступит второй запрос, который создаст новый фазер и начнет обработку, если исходный поток делегатора продвинет фазер, второй запрос / поток завершится. Есть идеи?

2. Документы Java 7 также, похоже, считают, что phaser.register(); в то время как (!phaser.isTerminated()) phaser.arriveAndAwaitAdvance(); является приемлемым подходом к использованию?

3. Это было бы лучше, поскольку вы не заняты вращением. Вы все еще ожидаете завершения работы фазеров.

4. Я думаю, главный вопрос в том, могут ли 2 экземпляра Phaser действовать независимо? т. Е., Если прибывают все стороны одного фазера, приводит ли это к увеличению фазы на другом? Или фаза каждого фазера специфична только для экземпляра этого фазера?

5. Последнее. Единственный случай, когда это неверно, — это если один фазер является родителем дочернего элемента (т. Е. : new Phaser(new Phaser()) )