Скажем, я делаю что-то на Java, например:
RemoteResponse response = null;
try {
FutureTask task new FutureTask(....);
executor.execute(task);
response = task.get(1000, TimeUnits.MILLISECONDS);
}
catch( TimeoutException te ) {
.. should I do something special here? ...
.. what happens to the return value of the task if task.get() throws an exception? ...
.. is it ever garbage collected? ..
}
Мой вопрос: есть ли что-то в RemoteResponse в случае возникновения исключения TimeoutException? Будет ли он собираться мусором? Должен ли я вызывать метод cancel () в задаче, чтобы это произошло?




Отредактируйте после того, как вопрос был изменен:
response - это ссылка на RemoteResponse, за размещение которого отвечает task. Назначение возвращаемого значения из метода не произойдет, если метод вызвал исключение, поэтому нет необходимости в специальной обработке response.
На task не будет ссылки, когда он выйдет за пределы области видимости либо в результате нормального выполнения, либо в случае возникновения исключения.
Если ресурсы, выделенные task, хорошо инкапсулированы, т. Е. Отсутствуют внешние ссылки, и они выпущены (close, release и т. д.), То утечки ресурсов быть не должно.
Нет необходимости вызывать отмену, если нет какого-то общего ресурса, который есть исключительно у task, или какого-либо другого расходуемого ресурса, который нужен остальной части приложения.
Я бы хотя бы записал тот факт, что задача не была выполнена в отведенное время. Что еще вы делаете, зависит от требований вашего приложения.
Обратите внимание, что task продолжит выполнение до завершения, независимо от вызова get.
Я думаю, что способ взглянуть на проблему состоит в том, что вам нужно запросить ресурс за пределами FutureTask, чтобы, когда вы решите отменить его, вы могли принудительно вернуть ресурсы.
так:
Resource res = null;
try {
resource = ResourceAquirer.claim()
FutureTask<?> task = new FutureTask<?>(resource);
executor.execute(task);
response = task.get(1000, TimeUnits.MILLISECONDS);
} catch (Exception e) {
// logging
} finally {
if (resource != null) {
resource.release();
}
}
Таким образом вы можете быть уверены, что ресурс освободится. Действительно досадно, что все это не может быть инкапсулировано в будущей задаче, но я не могу найти доказательств того, что вызов cancel для будущей задачи гарантирует, что блок finally будет вызываться внутри FutureTask. (Может быть, я задам еще один вопрос)
Если кто-то вызывает Future # cancel () для FutureTask и этот вызов фактически отменяет операцию - при условии, что она не была ранее отменена или уже не завершена, - будет вызван защищенный метод FutureTask # done (). В done () вы можете вызвать Future # isCancelled (), чтобы узнать, закончили ли вы в силу отмены. Другими словами, done () будет вызываться не более одного раза. Если вы никогда не вызываете run () или cancel () для FutureTask, done () никогда не будет вызываться.