Экземпляры 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.