JBoss 6.0 Final の非同期メソッド呼び出しに問題があります。
クラスは次のようになります。
1 つは、多数のオブジェクトを含むある種のストレージです。
@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 catch ブロックが呼び出されるため、基本的に非同期メソッドで無限ループを実行しても問題ありません。
アップデートⅡ
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);
}
どんな助けでも大歓迎です!
よろしく