J'ai un système d'interrogation/réponse asynchrone sous-jacente asynchrone que je veux rendre synchrone. Les requêtes et les réponses peuvent être mappées en marquant les requêtes avec des identifiants uniques qui, à leur tour, accompagneront les réponses correspondantes.Faire des requêtes asynchrones synchrones
Ma tentative pour la rendre synchrone utilise deux ConcurrentHashMap
s: une qui mappe des ID aux résultats, et une qui mappe des mêmes ID à CountDownLatch
es. Le code va comme ceci lors de l'exécution d'une requête:
public Result execute(Query query) throws InterruptedException {
int id = atomicInteger.incrementAndGet();
CountDownLatch latch = new CountDownLatch(1);
latchMap.put(id, latch);
query.executeAsyncWithId(id); // Probably returns before result is ready
try {
latch.await(); // Blocks until result is ready
return resultMap.remove(id);
} catch (InterruptedException e) {
latchMap.remove(id); // We are not waiting anymore
throw e;
}
}
Et le code pour traiter un résultat entrant:
public void handleResult(Result result) {
int id = result.getId();
CountDownLatch latch = latchMap.remove(id);
if (latch == null) {
return; // Nobody wants result
}
resultMap.put(id, result);
latch.countDown();
}
Cette méthode est appelée à partir d'un fil qui lit tous les résultats entrants du système sous-jacent (il n'y a qu'un seul thread de lecteur de ce type). Tout d'abord, je ne suis pas sûr de la sécurité des threads, mais il semble inutile d'utiliser deux HashMap
pour cela (en particulier parce que les ID ne sont jamais réutilisés). Des idées d'améliorations?
Supprimez donc le code qui utilise "verrou", mais il ne doit pas être défini dans cette fonction. Je ne vois rien qui puisse rendre cela asynchrone. –
C'est le système sous-jacent qui exécute réellement les requêtes asynchrones. J'ai renommé la méthode en "executeAsyncWithId" pour clarifier. – hakos
Heh, je vous suggère de poster votre propre réponse comme réponse, et acceptez-le! –