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

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

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

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

Метод 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 result;
    }
}

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

AnotherClass:

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 для каждого запроса - т.е. я создаю новый Phaser() каждый раз, когда запрос создает новый поток делегатора.

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

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

Благодарю.

1 ответ

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

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


Я делаю что-то неправильно?

Да. Не делай

while (!phaser.isTerminated()) {}

Занятый спиннинг убьет тебя. Вместо этого сделайте:

phaser.awaitAdvance();

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

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


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

Если у вас есть несколько неизвестных потоков, было бы полезно использовать Phaser.

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