Make asynchronous requests synchronous

I have a basic out-of-order asynchronous request / response system that I want to make synchronous. Requests and responses can be displayed by marking requests with unique identifiers, which, in turn, will accompany the corresponding responses.

My attempt to do this synchronously uses two ConcurrentHashMaps: one that displays from identifiers to results, and one that displays the same identifiers for CountDownLatch. When executing the request, the code is as follows:

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;
    }
}

And the code for processing the incoming result:

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();
}

This method is called from a stream that reads all incoming results from the base system (there is only one such read stream).

, , HashMap ( , ). ?

+3
3

, :

public class ResultFuture {

    private volatile Result result = null;
    private final CountDownLatch latch = new CountDownLatch(1);

    public Result get() throws InterruptedException {
        latch.await();
        return result;
    }

    public void set(Result result) {
        this.result = result;
        latch.countDown();
    }
}

HashMap ResultFuture s:

public Result execute(Query query) throws InterruptedException {
    int id = atomicInteger.incrementAndGet();
    ResultFuture resultFuture = new ResultFuture();
    resultFutureMap.put(id, resultFuture);
    query.executeAsyncWithId(id); // Probably returns before result is ready
    try {
        return resultFuture.get(); // Blocks until result is ready
    } finally {
        resultFutureMap.remove(id);
    }
}

public void handleResult(Result result) {
    int id = result.getId();
    ResultFuture resultFuture = resultFutureMap.get(id);
    if (resultFuture == null) {
        return; // Nobody wants result
    }
    resultFuture.set(result);
}
+4

ConcurrentHashMap , , , :

  • putIfAbsent(K key, V val)
  • replace(K key, V val)
  • remove(K key, V val)

, , , , , -.

Executor , , , : ..

0

, CountDownLatch, , . "Java Concurrency in Practice" ( ) ( , ). , , .

​​ wait() - notifyAll(), CountDownLatch .

CountDownLatch await () - countDown () methods provide the correct relationship-up relationship.

0
source

Source: https://habr.com/ru/post/1757495/


All Articles