简体   繁体   English

Java Spring异步将来及时阻止

[英]java spring async future block on timely manner

eg I looking to find a way to execute @Async method not absolutely asynchronously. 例如,我正在寻找一种方法,而不是绝对异步地执行@Async方法。 For example I want to invoke @Async task that will block my process for a up to a maximum defined time if task still haven't completed. 例如,我想调用@Async任务,如果任务仍未完成,它将在最长的定义时间内阻止我的进程。

@Async
public Future<ModelObject> doSomething() {
   //here we will block for a max allowed time if task still haven't been completed
}

So such code will be semi asynchronous but the blocking time can be controlled by developer. 这样的代码将是半异步的,但是阻塞时间可以由开发人员控制。

PS : of course I can achieve this by simply blocking calling thread for a limited time. PS:当然,我可以通过在有限的时间内阻塞调用线程来实现此目的。 but I look to achieve that within spring layer 但我希望在弹簧层内实现这一目标

In short, no, there is no way to configure Spring to do this. 简而言之,没有,没有办法配置Spring来做到这一点。

The @Async annotation is handled by the AsyncExecutionInterceptor which delegates the work to a AsyncTaskExecutor . @Async批注由AsyncExecutionInterceptor处理,该工作将工作委派给AsyncTaskExecutor You could, in theory, write your own implementation of the AsyncTaskExecutor but even then there would be no way to use the @Async annotation to pass the desired wait time to your executor. 从理论上讲,您可以编写自己的AsyncTaskExecutor实现,但是即使那样,也无法使用@Async注释将所需的等待时间传递给执行程序。 Even then, it's not clear to me what the caller's interface would look like since they'd still be getting a Future object back. 即使那样,我仍然不清楚调用者的界面是什么样子,因为他们仍将找回Future对象。 You would probably also need to subclass the Future object as well. 您可能还需要对Future对象进行子类化。 Basically, by the time you are finished, you will have written the entire feature again more or less from scratch. 基本上,到您完成时,您将或多或少地从头开始编写整个功能。

You could always wrap the returned Future object in your own WaitingFuture proxy which provides an alternate get implementation although even then you'd have no way of specifying the wait value on the callee side: 您始终可以将返回的Future对象包装在您自己的WaitingFuture代理中,该代理提供替代的get实现,尽管即使这样,您也无法在被调用方指定等待值:

WaitingFuture<ModelObject> future = new WaitingFuture<ModelObject>(service.doSomething());
ModelObject result = future.get(3000); //Instead of throwing a timeout, this impl could just return null if 3 seconds pass with no answer
if(result == null) {
    //Path A
} else {
    //Path B
}

Or if you don't want to write your own class then just catch the TimeoutException . 或者,如果您不想编写自己的类,则只需捕获TimeoutException

Future<ModelObject> future = doSomething();
try {
    ModelObject result = future.get(3000,TimeUnit.MILLISECONDS);
    //Path B
} catch (TimeoutException ex) {
    //Path A
}

You can do it with an @Async method that returns a Future: 您可以使用返回Future的@Async方法来执行此操作:

       Future<String> futureString = asyncTimeout(10000);
       futureString.get(5000, TimeUnit.MILLISECONDS);

       @Async
       public Future<String> asyncTimeout(long mills) throws InterruptedException {

               return new AsyncResult<String>(
                    sleepAndWake(mills)
               );
       }

        public String sleepAndWake(long mills) throws InterruptedException{
            Thread.sleep(mills);
            return "wake";
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM