7

我正在编写一个企业 Java 应用程序,它使用异步 EJB 3.1 方法并行执行多个任务。为了支持取消长时间运行的任务,我一直在尝试使用 Future 接口。

不幸的是future.cancel(true),尽管取消调用正在返回,但从客户端应用程序调用似乎对执行任务的 bean 的会话上下文没有影响true

我有一个简单的界面:

public interface AsyncInterface
{
    Future<Integer> run() throws Exception;
}

使用如下 bean 实现:

@Stateless
@Remote(AsyncInterface.class)
public class AsyncBean
{
    @Resource SessionContext myContext;

    @Asynchronous
    public Future<Integer> run() throws Exception
    {
        Integer result = 0;

        System.out.println("Running AsyncBean");

        while(myContext.wasCancelCalled() == false)
        {
            Thread.sleep(2000);
            System.out.println("Working");
        }      

        System.out.println("AsyncBean cancelled");

        return new AsyncResult<Integer>(result);
     }
}

客户端代码很简单:

InitialContext ctx = new InitialContext();
AsyncInterface async = (AsyncInterface)ctx.lookup("AsyncBean/remote");
Future<Integer> future = async.run();

if( future.cancel(true) )
{
     System.out.println("future.cancel() returned true");
}
else
{
     System.out.println("future.cancel() returned false");
}

bean的输出是源源不断的“Working”;它永远不会检测到取消。

如果相关,我在 JBoss Application Server 6.0.0 上运行该应用程序。我没有找到太多使用 Future 接口的取消功能的示例代码,所以我想知道我是否正确使用了 Future。这种用法看起来正确吗?取消异步 EJB 方法调用是否有更好的选择?

4

2 回答 2

3

回答我自己的问题 - 我发现 JBoss AS 6.0.0 不支持调用异步请求。

作为替代方案,我重构了代码以使用 JMS 请求/响应样式消息传递。

消息驱动 bean 用于执行异步操作。消息驱动 bean 创建一个临时队列并通过 JMS 将该队列返回给调用者。这是通过利用 JMS 消息的 replyTo 字段来实现的。

然后,消息驱动 bean 会定期检查临时队列中的取消消息。

这比 @Asynchronous 版本更复杂,但它适用于 JBoss AS 6.0.0。

于 2011-02-15T22:32:02.777 回答
2

您必须return使用一种Future对象类型,而不是null. 顺便问一下,你没有拿到 NPE 吗?我希望有一个,您的代码有问题。

此外,cancel()不应调用。请参阅此处的文档顺便说一句,根据文档,它不仅仅是不应该调用的cancel()方法,也不应该调用任何实例方法。这就引出了一个问题,为什么方法应该返回。我根本不知道,可能它在那里以备将来使用。但是类级别的注释表明所有方法都存在以便于将结果提供给容器。AsyncResult

因此,我不确定是否完全可以取消异步 EJB 调用。

[稍作研究后编辑]

试试这个实现,

@Stateless
@Remote(AsyncInterface.class)
public class AsyncBean
{
    @Resource SessionContext myContext;

    @Asynchronous
    public Integer run() throws Exception
    {
        Integer result = 0;

        System.out.println("Running AsyncBean");

        while(myContext.wasCancelCalled() == false)
        {
            Thread.sleep(2000);
            System.out.println("Working");
        }      

        System.out.println("AsyncBean cancelled");

        return result;
     }
}
于 2011-01-24T04:27:24.237 回答