java.util.concurrent предоставляет все, что вам нужно. Если я правильно понимаю ваш вопрос, у вас есть следующие требования:
Вы хотите отправить запрос и немедленно (в пределах разумного) обработать результат запроса (Ответ). Ну, я полагаю, что вы уже видели решение вашей проблемы: java.util.concurrent.CompletionService.
Этот сервис, который довольно просто комбинирует Executor и BlockingQueue для обработки задач Runnable и / или Callable. BlockingQueue используется для хранения выполненных задач, в результате чего другой поток может ожидать, пока завершенная задача не будет поставлена в очередь (это достигается путем вызова take ()) для объекта CompletionService.
Как уже упоминалось в предыдущих постерах, предоставьте общий доступ к Executor и создайте CompletionService для каждого запроса. Это может показаться дорогостоящим делом, но учтите еще раз, что CS просто сотрудничает с Исполнителем и BlockingQueue. Поскольку вы делите самый дорогой объект для создания экземпляра, то есть исполнителя, я думаю, вы обнаружите, что это очень разумная цена.
Однако ... несмотря на это, кажется, у вас все еще есть проблема, и эта проблема, похоже, заключается в отделении обработки Запросов от обработки Ответов. Это может быть достигнуто путем создания отдельной службы, которая обрабатывает исключительно ответы для всех запросов или для определенного типа запроса.
Вот пример:
(Примечание: подразумевается, что объект Request реализует интерфейс Callable, который должен возвращать тип Response ... подробности, которые я пропустил в этом простом примере).
class RequestHandler {
RequestHandler(ExecutorService responseExecutor, ResponseHandler responseHandler) {
this.responseQueue = ...
this.executor = ...
}
public void acceptRequest(List<Request> requestList) {
for(Request req : requestList) {
Response response = executor.submit(req);
responseHandler.handleResponse(response);
}
}
}
class ResponseHandler {
ReentrantLock lock;
ResponseHandler(ExecutorService responseExecutor) {
...
}
public void handleResponse(Response res) {
lock.lock() {
try {
responseExecutor.submit( new ResponseWorker(res) );
} finally {
lock.unlock();
}
}
private static class ResponseWorker implements Runnable {
ResponseWorker(Response response) {
response = ...
}
void processResponse() {
// process this response
}
public void run() {
processResponse();
}
}
}
Несколько вещей, которые нужно запомнить: во-первых, ExecutorService выполняет Callables или Runnables из очереди блокировки; ваш RequestHandler получает задачи, которые ставятся в очередь на исполнителя и обрабатываются как можно скорее. То же самое происходит в вашем ResponseHandler; ответ получен, и как только этот отдельный исполнитель сможет, он обработает этот ответ. Короче говоря, у вас одновременно работают два исполнителя: один на объектах запроса, другой на объектах ответа.