1

我有一个具有请求映射的 spring @Controller。当向它发送请求时,它会创建一个延迟结果并在委托类上运行一个方法。

在控制器中:

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

委托器中的 doStuff 方法是 @Async 注释的 - 所以它在另一个线程中运行。在这个线程中,创建了一个新的 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 调用创建,这里向移相器注册自己,做一些工作,然后到达并取消注册。

另一个类:

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()) {}

将继续,设置其延迟结果,委托线程将结束。

所以这里的问题(S):

我希望每个请求都有一个 Phaser - 即,每次请求创建一个新的委托线程时,我都会创建一个新的 Phaser()。

如果我收到 5 个对我的控制器的请求,它们每个都会产生一个委托线程,每个委托人都会创建一个新的 Phaser 并将其传递给他们的孩子。然而,一旦其中一个线程完成了它的处理并且它的 Phaser 的特定实例被终止,其他委托线程继续并返回而没有完成它们的任务。

相位器可以这样使用吗?难道我做错了什么?我认为这将是跟踪子线程完成并等待它们完成的有用方法?

谢谢。

4

1 回答 1

0

相位器可以这样使用吗?

是的,它可以像这样使用,通常用作同步屏障。


难道我做错了什么?

是的。不要做

while (!phaser.isTerminated()) {}

忙碌的旋转会杀死你。而是这样做:

phaser.awaitAdvance();

这将迫使您以不同的方式注册。在实际开始运行之前,您必须注册一个线程。

此外,如果您正在推进具有多个阶段的移相器,那么您将不得不使用移相器重新评估。


我认为这将是跟踪子线程完成并等待它们完成的有用方法?

如果您确实创建了许多未知线程,则使用 Phaser 会很有用。

于 2014-06-18T13:36:00.160 回答