[concurrency-interest] syntax sugar for lazy instantiation

Ben Manes ben_manes at yahoo.com
Tue Jun 23 14:19:22 EDT 2009


I use this trick all the time, but its already supplied via FutureTask.  It has very similar semantics to your code.  This trick can be extended to build lazy maps (and other lazy structures) which is also very convenient.

public class Example {
    private final FutureTask<Computation> future = new FutureTask<Computation>(new Computable());

    // Lazily computes the work and returns the value
    public Computation getComputation() throws Exception {
        future.run(); // no-ops on all subsequent calls
        return future.get();
    }

    private static final class Computable implements Callable<Computation> {
        public Computation call() {
          // do work, return
        }
    }
}




________________________________
From: Ashley Williams <ashpublic at mac.com>
To: concurrency-interest at cs.oswego.edu
Sent: Tuesday, June 23, 2009 10:05:24 AM
Subject: [concurrency-interest] syntax sugar for lazy instantiation


It seems to me that the only reason to use an intrinsic lock on a lazy getter (stick a synchronized keyword
on the method signature) is convenience of syntax. Please correct me if I am wrong.

So is one idea to simplify lazy instantiation, feedback welcome if anybody can improve on it. It's based
on the observation that double checked locking is mostly boilerplate except for the line that creates
the instance and so I've factored it out into a callable interface.

Admittedly the anonymous class makes for a more verbose constructor, but at least the dcl logic is
now encapsulated. And if java had support for closures then the readability problem would go away.

So first the class:

@ThreadSafe
public final class LazyField<T> {
privatevolatileT obj;
private final Callable<T> callable;

public LazyField(Callable<T> callable) {
this.callable = callable;
}

public T get() {
if (obj == null) {
synchronized(this) {
if (obj == null) {
obj = callable.call();
}
}
}
returnobj;
}
}

and here is an example usage:


@ThreadSafe
public final class MyClass {
private final LazyField<String> message;


public MyClass() {
this.message = new LazyField<String>(new Callable<String>() {
public String call() throws Exception {
return "hello world";
}
});
}

public String getMessage() {
returnmessage.get();
}
}

- Ashley Williams


      
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090623/d8c32356/attachment-0001.html>


More information about the Concurrency-interest mailing list