Я работаю над проектом, у которого есть пул потоков, которому он представляет задачи. Каждая задача - это цепочка, так сказать. Когда задача выполняется, она выполняет то, что ей нужно, а затем проверяет результат. Каждая из этих задач содержит карту результатов (которая представляет собой просто перечисление) и дополнительные задачи. Они вызываются внутри одного потока, и цикл повторяется до тех пор, пока не будет больше задач, после чего он вернется в цепочку, добавив каждый результат в коллекцию и вернув это в основной поток. Q & D Пример:Java Future <T>, TimeoutException и получение частичных результатов
public abstract class MyCallable implements Callable<MyResponse> {
private Map<ResponseEnum, List<MyCallable>> callbacks;
public List<MyResponse> call() {
List<MyResponse> resp = new ArrayList<MyResponse>();
try{
//Run the process method and collect the result
MyResponse response = process();
List<MyCallable> next = callbacks.get(response.getResult());
if (next != null && !next.isEmpty()){
//Run within same thread, return results
for (MyCallable m : next){
resp.addAll(m.call();
}
return resp;
} else {
//No more responses, pass them back up the chain
resp.add(response);
return list;
}
//Anything goes wrong, we catch it here and wrap it in a response
} catch (Exception e){
resp.add(new MyExceptionResponse(e));
return resp;
}
}
//Implemented by all child classes, does the actual work
public abstract MyResponse process() throws Exception;
Имейте в виду, что это также опытный образец, который я до сих пор на самом деле не проверял, так что я знаю, что это не может быть совершенным или обязательно полностью осуществимо.
У меня есть проблема: задача добавлена в пул потоков и начинает выполнение. В основном потоке создается Будущее и на него вызывается функция .get (N, TimeUnit) для извлечения результата. Что делать, если эта задача не работает? Мы получаем исключение TimeoutException. Теперь, в блоке try/catch я мог бы отменить Будущее, но есть ли способ отменить будущее и извлечь результаты, по крайней мере, насколько они идут? Три задачи, возможно, выполнили и вернули результаты до того, как четвертый остановился. Try/catch в MyCallable должен возвращать результат и нажимать его на цепочку, если есть исключение (Ie, InterruptedException, когда вызывается .cancel (true)), но возможно ли получить этот результат?
Конечно, если я собираюсь сделать это совершенно неправильно в первую очередь, это было бы также полезно знать. Это мой первый большой набег на многопоточность.
EDIT: Хорошо, с учетом этого, оболочка была помещена вокруг класса MyCallable. Обертка реализует Callable и возвращает коллекцию. Коллекция передается по цепочке объектов MyCallable и добавляются результаты, поэтому, если время ожидания Future.get, мы можем получить сбор и получить частичные результаты.
Однако это вызывает потенциальное состояние гонки. Если текущий вызов MyCallable ожидает внешнего сервиса, то операция Future.cancel (true) вызовет InterruptedException в MyCallable. Это поймано, и исключение обернуто в объект ответа и добавлено в коллекцию. Дело в том, что если основной поток отменяет будущее, синхронизируется на обертке или коллекции в оболочке, а затем получает коллекцию, это создаст условие гонки между получением коллекции и блоком try/catch в добавлении MyCallable завернутое исключение из коллекции? Или будет ли основной поток ждать улавливания исключения и затем выполнить следующую строку?
Карта используется только в качестве дерева решений, чтобы получить следующий MyCallable. Когда текущий результат приходит, он используется для получения следующего MyCallable с карты и выполнения этого и т. Д. Возможно, возможно сделать доступным набор результатов, что может быть необходимо, так как я не могу получить результаты из отмененного Будущего без моего собственного будущего класса. – user1017413
Просто не используйте возвращаемое значение в качестве канала связи. Храните накопленные результаты в том месте, где вы можете получить их независимо от механизма Future. –
Определенно выполнимый, я полагаю, но теперь, чтобы найти лучший способ.Возможно, возьмите эти объекты MyCallable и поместите их в оболочку, которая сама реализует Callable, которая затем вызывает MyCallables и передает им коллекцию, которая заполняется ... – user1017413