У меня есть код, который я хочу выполнить с помощью одной инициализации. Но этот код не имеет определенного жизненного цикла, поэтому моя логика может быть потенциально вызвана несколькими потоками до моей инициализации. Поэтому я хочу в основном убедиться, что мой логический код «ждет» до тех пор, пока не будет выполнена инициализация.Контроль состояния гонки при запуске
Это мой первый разрез.
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
synchronized(initialised) {
initStuff();
initialised.getAndSet(true);
initialised.notifyAll();
}
}
public void doStuff() {
synchronized(initialised) {
if (!initialised.get()) {
try {
initialised.wait();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
}
}
doOtherStuff();
}
}
Я в принципе хочу, чтобы убедиться, что это будет делать то, что я думаю, что это будет делать - блок DoStuff до тех пор, пока инициализируются верно, и что я не хватает условия гонки, где DoStuff может застрять на Object.wait(), который никогда не появится.
Edit:
Я не имею никакого контроля над потоками. И я хочу иметь возможность контролировать, когда вся инициализация выполнена, поэтому doStuff() не может вызвать initialise().
Я использовал AtomicBoolean, поскольку это была комбинация держателя значений, и объект, который я мог бы синхронизировать. Я мог бы также просто иметь «общедоступный статический окончательный объект Lock = new Object();» и простой булевский флаг. AtomicBoolean удобно дал мне обоим. Логическое значение не может быть изменено.
CountDownLatch - именно то, что я искал. Я также рассмотрел использование Sempahore с 0 разрешениями. Но CountDownLatch идеально подходит для этой задачи.
Почему бы не использовать статический инициализатор? –
где инициализируется вызов? – luke
Вы запускаете поток в своем конструкторе для выполнения инициализации или нет? – rmarimon