这里的伪代码:
//-- 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);
注意: 对下游服务的调用是:
让我们说下游服务是一个websocket客户端。服务器发送消息并等待响应。
关于 requestIdToResponseMap ,我尝试了3个解决方案:
那么,对于这类问题,通常的解决方案是什么?
答案 0 :(得分:0)
您没有详细说明您的使用案例,因此我一般会回答这个问题:
Java有多个framework用于多线程消费者 - 生产者案例。如果你发现自己正在考虑锁和线程原语,你可能会重新发明轮子。专注于重要的事情:-)
这是一个让你入门的片段:
// 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();
您的RequestTask
实施Callable
:
private static class RequestTask implements Callable<Response> {
@Override
public Response call() throws Exception {
...
}
}
为了清楚起见,你的制作人主题是&#34;主要&#34;线程(在您的示例中为A),而使用者位于线程池(线程B)中。您可以增加线程池大小(在一定程度上)以增加请求吞吐量。
有大量关于Java的ExecutorService和生产者 - 消费者模式的引用。请记住,在生产者和消费者线程之间有一个队列,因为您可以生成比您可以使用的更快的请求。它默认无限制,非常重要的是要记住它!
如果您还有其他问题,请告诉我们。
答案 1 :(得分:0)
创建将存储reponsefuture的地图,如果结果不可用将阻塞,线程将等待。您可以使用其他功能进行修改,例如等待多长时间。
private static ConcurrentHashMap<String, ExecutorSeriveInstanceFuture> instanceMap = new ConcurrentHashMap<String, ExecutorSeriveInstanceFuture>();
自定义Future,以便您可以根据用例进行修改。
private static class ExecutorSeriveInstanceFuture {
private DBExecutorSerive dbExecutorSerive;
private Throwable throwable;
private Object lock = new Object();
public DBExecutorSerive get() {
if (dbExecutorSerive == null) {
return dbExecutorSerive;
}
boolean restoreInterrupt = false;
synchronized (lock) {
while (dbExecutorSerive == null && throwable == null) {
try {
lock.wait();
} catch (InterruptedException e) {
restoreInterrupt = true;
}
}
}
if (restoreInterrupt) {
Thread.currentThread().interrupt();
}
if (dbExecutorSerive != null) {
return dbExecutorSerive;
}
throw new IllegalStateException(throwable);
}
public void set(DBExecutorSerive dbExecutorSerive) {
synchronized (lock) {
this.dbExecutorSerive = dbExecutorSerive;
lock.notifyAll();
}
}
public void setFailure(Throwable throwable) {
synchronized (lock) {
this.throwable = throwable;
lock.notifyAll();
}
}
}