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?
Posted by digulla