4

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

有谁知道我该怎么做?

4

3 回答 3

2

了解异步进程的进度总是很棘手,特别是如果您不知道它们是否真正开始了。

我发现的最好方法是编写另一个只获取进度的函数,因此,如果每次调用都有一些唯一的 id,则hashmap使用当前进程更新 a 。您可能想查看并发哈希图(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 的原因,这样你就不必担心并发写入,所以锁定注意事项。

于 2010-07-31T17:56:48.033 回答
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
        }
    }
}
于 2017-08-22T14:17:25.210 回答
0

在 EJB3.1,@Asynchronous方法调用可以返回java.util.concurrent.Future,此接口提供信息boolean isCancelled()boolean isDone(),但不提供执行是否开始的信息。在我看来,如果流程以标准方式通过 EJB-Container 开始执行,则无法获取信息。

于 2010-07-31T20:55:29.723 回答