Следующему классу лень инициализировать себя обычным путём, поэтому он делает это на фоновом потоке. Что программа напечатает? Гарантируется одинаковый результат для каждого запуска?
public class Lazy {
private static boolean initialized = false;
static {
Thread thread = new Thread(
new Runnable {
public void run() {
initialized = true;
}
}
);
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
throw new AssertionError(ie);
}
}
public static void main(String[] args) {
System.out.println(initialized);
}
}
Кажется, что программа должна каждый раз печатать true, но нет! Она просто виснет.
Симпатичный deadlock. Попробую объяснить.
Понятно, что при обращении к методу
main
JVM начинает инициализировать класс. И только когда инициализация закончится будет вызван метод
main
. Во время инициализации запускается метод
run
. Однако, этот метод перед установкой
initialized
в
true
делает тоже проверку на то, что класс уже проинициализирован. Таким образом получается, что основной поток ждёт завершения фонового потока для завершения инициализации, а фоновый поток ждёт завершения инициализации. Вуаля!