2

嗨,JBoss 6.0 Final 中的异步方法调用有问题。

这些类如下所示:

一个只是某种包含许多对象的存储。

@Singleton
public class Storage {

    private Map<Integer, Object> storage = new HashMap<Integer, Object>();

    @Asynchronous
    public Future<Object> getAsync(int id) {
        Object obj = null;
        while (null == obj ) {
          obj = storage .remove(id);
        }
        return new AsyncResult<Object>(obj);
    }

    public void add(int id, Object obj) {
        storage.put(id, obj(    
    }
}

然后有一个类处理某些东西并尝试从存储中找到具有给定 id 的对象。它应该等待指定的时间才能从存储中找到该id的对象。如果什么都没有,请停止搜索并继续:

@Singleton
public class Executor {

    @Inject
    private Storage storage;

    public void execute(int id) {

        Future<Object> fut = storage.getAsync(id);
        Object obj; 
        try {
            obj = t.get(30L, TimeUnit.SECONDS);
                    // go on processing of obj is found
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            //no object can be found.
            // but we never reach this place
        }
    }
}

存储中可能没有给定 ID 的对象,因此 getAsync() 方法中的循环是“无限的”。这就是为什么应该在 30 秒后抛出 TimeoutException。有趣的是,TimeoutException 永远不会被抛出。

我是否遗漏了一点,例如不要在异步方法中创建“无限”循环?

更新:

当我在独立应用程序上做类似的事情时,它工作正常:

public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        Callable<Object> task = new Callable<Object>() {
          public Object call() {
              int i = 0;
              while(i == 0) {
                  i = 0;
              }
               return null;
          }
        };
        Future<Object> future = executor.submit(task);
        try {
          Object result = future.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException ex) {
            ex.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

所以基本上在异步方法中做一个无限循环是可以的,因为在独立的 TimeoutException 捕获块被调用!

更新二

当我用getAsync()与此类似的方法替换该方法时,get()成功返回而不会抛出 TimeoutException。但这就是我所期望的!

@Asynchronous
public Future<Telegram> getTelegramAsync(int telegramId) {
    Telegram tlgrm = null;
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return new AsyncResult<Telegram>(tlgrm);
}

任何帮助,将不胜感激!

问候

4

1 回答 1

0

没有超时异常,因为t.get永远不会执行。你被困在 while 循环中getAsync。您需要立即返回 Future 并且在 Future-Implementation 中,您需要使用一些 countdownlatch 例如等待结果可用或超时...

于 2012-11-09T10:26:17.787 回答