Java Tricks: Lazy initialization

If you’re a Java developer and you’re concerned about performance, you’ve probably encountered the (broken) double checked locking pattern (which I won’t reproduce here to make sure no one copies it accidentally. If you care, read the Wikipedia article).

Joshua Block has proposed a solution but there are a couple of fine points to it. If you don’t get it right, things are going to break in odd ways. So this should go into a helper class which handles all the boiler plate code. A post about final variables pointed me in the right direction. So without further ado, the LazyInit class:

/** Lazy initialization of a field value based on the (correct)
 * double checked locking idiom by Joschua Bloch
 * 
 * <p>See "Effective Java, Second Edition", p. 283
 */
public abstract class LazyInit<T>
{
    private volatile T field;
    
    /** Return the value.
     * 
     *  <p>If the value is still <code>null</code>, the method will block and
     *  invoke <code>computeValue()</code>. Calls from other threads will wait
     *  until the call from the first thread will complete.
     */
    public T get ()
    {
        T result = field;
        if (result == null) // First check (no locking)
        {
            synchronized (this)
            {
                result = field;
                if (result == null) // Second check (with locking)
                {
                    field = result = computeValue ();
                }
            }
        }
        return result;
    }

    protected abstract T computeValue ();
    
    /** Setter for tests */
    public synchronized void set (T value)
    {
        field = value;
    }
}

As an additional goodie, it allows you to override the value in tests. Here is how to use this code:

    private LazyInit<String> field1 = new LazyInit<String> () {
        
        @Override
        protected String computeValue ()
        {
            return "value";
        }
    };

    @Test
    public void testLazyInit () throws Exception
    {
        assertEquals ("value", field1.get ());
    }

Simple, isn’t it?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s