Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java how to get a map value in future?

Here's pseudo code:

//-- Thread A
sender.send(requestId, request);
// Wait receiver to receive response for that requestId
return requestIdToResponseMap.get(requestId);


//--- Thread B
response = receiver.receive();
requestIdToResponseMap.put(response.requestId, response);

Note: The call to downstream service is:

  1. time consuming
  2. asynchronized (i.e. response for request can only be mapped by request-id)

Let's say downstream service is a websocket client. The server sends messages and waits for responses.

About the requestIdToResponseMap, I tried 3 solutions:

  1. Use a requestIdToLockMap to hold the locks, and use requestIdToResponseMap to hold the response values, but it seems complicated.
  2. Use Map< String, Optional< Response>>, but Optional is immutable, I can not change its value. This doesn't work.
  3. Use Map< String, Pair< Lock, Response>>, the receiver notifies the corresponding lock, then sender thread gets notified and retrieves the value.

So, for this kind of problem, what's the usual solution?

like image 235
user1633272 Avatar asked Feb 24 '26 11:02

user1633272


1 Answers

You didn't go into detail on your use case, so I'll answer the question generally:

Java has an entire framework for multi-threaded consumer-producer cases. If you find yourself thinking about locks and thread primitives, you're probably reinventing the wheel. Focus on the important stuff :-)

Here's a snippet to get you started:

 // create your thread pool, threads here will consume your "requests"
 ExecutorService threadPool = Executors.newFixedThreadPool(1);
 // submit a request to the pool. This gets enqueued on a queue, until it is picked up by a thread. Returns a future- a reference to the uncompleted work
 Future<Response> future = threadPool.submit(new RequestTask<Response>(request, requestId));
 // wait for the work to complete
 Response response = future.get();

your RequestTask implements Callable:

   private static class RequestTask implements Callable<Response> {
        @Override
        public Response call() throws Exception {
            ...
        }
    }

Just to be clear, your producer thread is the "main" thread (A in your example) and the consumer is in the thread pool (thread B). You can increase your thread pool size (to a certain extent) to increase your request throughput.

There's tons of references about Java's ExecutorService and producer-consumer pattern. Remember that you have a queue in between producer and consumer threads, since you may produce requests faster than you can consume. It's unbounded by default, very important to remember that!

Let us know if you have any more questions.

like image 158
Vince Mannino Avatar answered Feb 27 '26 02:02

Vince Mannino