Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Noncompliant Code Example

Wiki MarkupThis noncompliant code example begins initializing the class {{Lazy}}. The code in the {{static}} block is responsible for initialization and starts a background thread which is in a different (anonymous) class. The anonymous class attempts to assign to the {{initialized}} field but has to wait before initialization of the {{Lazy}} class has finished. However, the {{Lazy}} class's main thread invokes the {{join()}} method which waits for the background thread to finish. This interdependency causes a class initialization cycle that results in a deadlock situation. \[[Bloch 05b|AA. Java References#Bloch 05b]\]

Code Block
bgColor#FFcccc
public class Lazy {
  private static volatile boolean initialized = false;
  static {
    Thread t = new Thread(new Runnable() {
      public void run() {
        // Initialize, for example, a database connection
        initialized = true;
      }
    );
    
    t.start();
    try {
      t.join();
    } catch(InterruptedException ie) {
        throw new AssertionError(ie);
    }
    // Other initialization
  }
  public static void main(String[] args) {
    System.out.println(initialized);
  }
}

Wiki Markup
The code in the {{static}} block is responsible for initialization, and starts a background thread. The background thread attempts to assign to the {{initialized}} field but has to wait before initialization of the {{Lazy}} class has finished. However, the {{Lazy}} class's main thread invokes the {{join()}} method which waits for the background thread to finish. This interdependency causes a class initialization cycle that results in a deadlock situation. \[[Bloch 05b|AA. Java References#Bloch 05b]\] 

Compliant Solution (static initializer)

...

Code Block
bgColor#ccccff
public class Lazy {
  private static volatile boolean initialized = false;

  private static final ThreadLocal<Connection> connectionHolder
    = new ThreadLocal<Connection>() {
        public Connection initialValue() {
          try {
            Connection conn = DriverManager.getConnection("connectionstring");
            initialized = true;
	    return conn;
	  } catch (SQLException e) {
	    return null;
	  }
        }
  };
    
  public static Connection getConnection() {
    return connectionHolder.get();
  }

  public static void main(String[] args) {
    Connection conn = getConnection();
    System.out.println(initialized);
  }
}

...