3

我尝试让异步进程运行。基于这个例子:http ://tomee.apache.org/examples-trunk/async-methods/README.html

但是只有当代码完全完成时,该方法addWorkflow(Workflow workflow)才会返回。run(Workflow workflow)

然后当它返回并被result.get();调用时,我会得到异常:

原因:java.lang.IllegalStateException:对象不代表实际的未来

任何建议我错过了什么?

@Singleton
public class WorkflowProcessor {

@EJB
private  WorkflowManager workflowManager;

private final static Logger log = Logger.getLogger(WorkflowProcessor.class.getName());



public void runWorkflows(Collection<Workflow> workflows) throws Exception{  
    final long start = System.nanoTime();
    final long numberOfWorkflows = workflows.size();
    Collection<Future<Workflow>> asyncWorkflows = new ArrayList<>();

    for(Workflow workflow : workflows){
        Future<Workflow> w = addWorkflow(workflow);
        asyncWorkflows.add(w);
    }    
    log.log(Level.INFO, "workflow jobs added {0}", new Object[]{numberOfWorkflows});
    for(Future<Workflow> result : asyncWorkflows){
       result.get();
    }

    final long total = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
    log.log(Level.INFO, "WorkflowProcessor->runWorkflows {0} workflows completed in:{1}", new Object[]{numberOfWorkflows, total});

}

@Asynchronous
@Lock(LockType.READ)
@AccessTimeout(-1)
private Future<Workflow> addWorkflow(Workflow workflow){

    run(workflow);

    return new AsyncResult<Workflow>(workflow);                
}


private void run(Workflow workflow){
    this.workflowManager.runWorkflow(workflow);
}
4

2 回答 2

7

因此,通常的方法是在调用者方法的另一个 bean 中使用 @Asynchronous 方法。

@Stateless
public class ComputationProcessor {

 @Asynchronous
 public Future<Data> performComputation {
   return new AsyncResult<Data>(null);
 }
}

@Stateless
public class ComputationService {

 @Inject
 private ComputationProcessor mProcessor;

 public void ...() {
   Future<Data> result = mProcessor.performComputation();
   ...
 }
}

正如您所发现的,如果 @Asynchronous 方法与调用者在同一个 bean 中,它将不起作用。

于 2014-01-10T07:52:56.880 回答
4

问题是 Java 不能修饰隐式 this 指针。

换句话说,@Asynchronous 注释不会被处理,而你正在做一个普通的方法调用。

您可以使用对自身的引用来注入您的 so 单例(称之为“self”),然后调用 self.addWorkflow。

您可能还想考虑在无状态 bean 中运行异步代码。您正在为 addWorkflow 使用读锁,但 runWorkflow 仍然有写锁。我认为你现在有一个死锁:你一直持有锁直到工作完成,但在写锁被释放之前无法完成任何工作。

于 2013-02-08T19:35:25.153 回答