我正在尝试从EJB异步流程中获取进度的百分比。这可能吗?
有没有人知道我该怎么做?
答案 0 :(得分:2)
要了解异步进程的进度总是很棘手,特别是如果你不知道它们是否真的已经启动了。
我找到的最好的方法是编写另一个只获得进度的函数,因此,如果每个调用都有一个唯一的id,那么使用当前进程更新hashmap
。您可能希望查看Concurrent Hashmap(http://download-llnw.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html)
然后这个其他查找函数将获取唯一ID,并将进度返回给客户端。
如果尚未启动,您也可以将其返回,理想情况下,您可能还希望能够返回处理过程中出现的任何错误消息。
然后,当它完成,并且您返回错误消息或成功,然后从hashmap中删除它,客户端获取信息,并且该信息不会改变,所以没有必要保留它。
<强>更新强>
在你的界面中创建一个新功能
String progressDone(String id);
然后,您将同步引用它,因为它刚刚退出并立即返回,因此它可以在id
中查找hashmap
并返回完成百分比或错误消息。
但是,这意味着你的实际工作者函数需要经常将信息放在hashmap中的位置,这就是为什么我建议使用并发hashmap,这样你就不必担心并发写入了等锁定因素。
答案 1 :(得分:1)
我找到的解决方案是异步方法和主线程之间共享的上下文对象。这是一个例子:
异步工作本身:
@Stateless
public class AsyncRunner implements AsyncRunnerLocal {
@Asynchronous
public Future<ResultObject> doWorkAsynchronous(WorkContext context) {
context.setRunning(true);
for (int i = 0; i < 100; i++) {
//Do the next iteration of your work here
context.setProgress(i);
}
context.setRunning(false);
return new AsyncResult(new ResultObject());
}
}
共享上下文对象。这里重要的是volatile关键字。字段值将在没有它的情况下在每个线程中本地缓存,并且在主线程中不会显示进度:
public class WorkContext {
//volatile is important!
private volatile Integer progress = 0;
private volatile boolean running = false;
//getters and setters are omitted
}
用法示例:
public class ProgressChecker {
@EJB
private AsyncRunnerLocal asyncRunner;
private WorkContext context;
private Future<ResultObject> future;
public void startJob() {
this.context = new WorkContext();
future = asyncRunner.doWorkAsynchronous(this.context);
//the job is running now
while (!future.isDone()) {
System.out.println("Progress: " + this.context.getProgress());
Thread.sleep(1000); //try catch is omitted
}
}
}
答案 2 :(得分:0)
在EJB3.1中@Asynchronous方法调用可以返回java.util.concurrent.Future,此接口提供信息boolean isCancelled()或boolean isDone(),但是如果执行开始则没有信息。从我的角度来看,如果流程以标准方式通过EJB-Container开始执行,则无法获取信息。