Предположим, что задача, представленная в пул исполнителей, выглядит
class Task implements Future<Boolean> {
public HeavyClass heavyClass;
public Task(HeavyClass heavyClass) {
this.heavyClass = heavyClass;
}
public Boolean call() {
try {
//do changes to heavyClass
return true;
} catch(Exception e) {
return false;
}
}
NOw в вызывающем потоке, который я делаю
Future<boolean> future = executor.submit(new Task(heavyClass));
try {
boolean success = future.get();
if (success) {
//Assume all changes made to heavyClass are visible
}
}
Это верно? По моему мнению, это не совсем правильно. Каков наилучший способ обеспечить исправление в таких сценариях?
Это должно быть хорошо. Любая жизнеспособная реализация Future
должна быть написана таким образом, что ее завершение включает в себя забор, а проверка на завершение включает в себя приобретение забора. Все предыдущие изменения в вашем heavyClass
должны быть heavyClass
, если Future
будет отмечено как завершенное и должно быть гарантировано видимым для других потоков к моменту завершения состояния задачи.
Опора на это, конечно, означает доверие к тому, что тот, кто реализовал исполнителя, знал, что они делают. Если вы используете одного из основных исполнителей Java, вы должны быть в порядке.
Одна из приятных вещей в Future
заключается в том, что вам не нужно беспокоиться об этом вопросе. Из документации:
Эффекты согласованности памяти. Действия, выполняемые асинхронным вычислением, происходят до действий, следующих за соответствующим Future.get() в другом потоке.
Поэтому, несмотря на то, что ваша задача не делает ничего для обеспечения видимости результатов между потоками, реализация Executor
позаботится об этом для вас.