You're not just starting another thread - you're joining on it. That new thread has to wait for StaticInitializer
to be fully initialized before it can proceed, because it's trying to set the state
field... and initialization is already in progress, so it waits. However, it's going to be waiting forever, because that initialization is waiting for that new thread to terminate. Classic deadlock.
See the Java Language Specification section 12.4.2 for details about what's involved in class initialization. Importantly, the initializing thread will "own" the monitor for StaticInitializer.class
, but the new thread will be waiting to acquire that monitor.
In other words, your code is a bit like this non-initializer code (exception handling elided).
final Object foo = new Object();
synchronized (foo)
{
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (foo) {
System.out.println("In the new thread!");
}
});
t1.start();
t1.join();
});
If you can understand why that code would deadlock, it's basically the same for your code.
The moral is not to do much work in static initializers.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…