有没有办法知道EJB异步进程的进度?

时间:2010-07-31 17:46:17

标签: java asynchronous ejb ejb-3.1

我正在尝试从EJB异步流程中获取进度的百分比。这可能吗?

有没有人知道我该怎么做?

3 个答案:

答案 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开始执行,则无法获取信息。