2017-06-21 54 views
1

我公开无状态EJB作为REST服务。在我的POST方法,我称之为Java:取消REST服务方法执行

Result r = longRunningBusinessMethod(); 
//return data 

如何去使其能够取消longRunningBusinessMethod()从客户端执行? 我想过为该方法创建一个线程,并将所有正在执行的线程与一个ID一起保存在散列表中,以便用户可以发布其ID以终止该线程。但我相信必须有更好的解决方案。 任何帮助将不胜感激。

回答

1

我认为“保留ID表”的粗略设计是一个很好的起点。我可能会使用带有线程池的ExecutorService,然后保留Map<ID, Future>,以便取消未来。 (同时确保每个将来从地图上删除自身,因为它成功完成异常。)

您还可以实现longRunningBusinessMethod,使其包含足够的地方,它检查看它是否被中断 - 取消未来只会在线程上设置中断标志,它实际上并不会停止执行代码。如果您的长时间运行方法已经丢弃InterruptedException,那就好了。否则,您需要添加一些虚拟电话,如Thread.sleep(1),或者每隔一段时间手动检查Thread.interrupted(),然后自己抛出InterruptedException

+0

这就是我将如何做到这一点。而我不知道我必须手动终止我的线程。简短和相关的问题:当我使用'Future#get(30,TimeUnit.Seconds)'时,底层方法在超时异常被抛出后仍然会执行吗? – User9123

+0

当超时异常被抛出时,底层方法_may_仍然在执行。这只会在正在执行'longRunningBusinessMethod'的线程上设置'interrupt'标志,因此代码仍然需要以可中断的方式编写。 –

1

中断工作线程总是很棘手,一般不推荐。一种解决方法是修改正在运行的业务方法,询问是否应完成其执行。例如:

public void longRunningBusinessMethod(JobContext context){ 
    while(someCondition) { 
     if(shouldInterrupt(context)){ 
      log.info("Interrupting longRunningBusinessMethod"); 
      ... 
      <close all the resources and terminate the job> 
     } 
    } 
} 

shouldInterrupt(context)将采取与作业ID在它的工作范围内,并会要求DB或缓存它是否应该被中断。然后,通过REST API很容易在DB或高速缓存中为此特定作业更改'shouldInterrup'值。