31

I was doing some research about singletons, specifically regarding lazy vs eager initialization of singletons.

An example of eager initialization:

public class Singleton
{
    //initialzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}

but as shown above that it is eager initialization and thread safety is left to jvm but now, I want to have this same pattern but with lazy initialization.

so I come up with this approach:

public final class Foo {
    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }
    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }
    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }
}

As shown above Since the line

private static final Foo INSTANCE = new Foo(); 

is only executed when the class FooLoader is actually used, this takes care of the lazy instantiation, and is it guaranteed to be thread safe.

Is this correct?

Kylar
  • 8,876
  • 8
  • 41
  • 75
tuntun fdg
  • 491
  • 2
  • 8
  • 12
  • 1
    Duplicate http://stackoverflow.com/q/5842273/823393 – OldCurmudgeon Apr 03 '13 at 16:00
  • 1
    This is not really lazy initialization though? The instance can be loaded prior to the `getInstance` method being invoked. – Perception Apr 03 '13 at 16:00
  • This is certainly lazy. The `INSTANCE` is only instantiated on first reference of the class. Which will only be referenced in the first invocation of `getInstance`. Though I would remove the creation check in the constructor. – John Vint Apr 03 '13 at 16:06
  • @JohnVint - tell me, what would happen if I did this - `Class.forName("Foo")`? – Perception Apr 04 '13 at 00:23
  • 1
    it will create the instace of the Foo class. That initialixation includes static fields and thr static block. It does not include static child classes. you can try it yourself to see. – John Vint Apr 04 '13 at 01:35
  • This is the Holder pattern. – Adam Oct 30 '18 at 11:53

5 Answers5

26

Your second code snippet is, in my opinion, the best way of thread-safe lazily initializing a singleton. It actually has a pattern name

Initialization-on-demand holder idiom

I would suggest you use it.

Josiah Yoder
  • 3,321
  • 4
  • 40
  • 58
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • Thanks a lot. gone through the article perfect explnation – tuntun fdg Apr 03 '13 at 16:46
  • Replying on the class loading behavior of the JVM rather than making your laziness explicit sounds to me like a bad idea. There's probably even no performance benefit compared to the straightforward way. – einpoklum Apr 04 '13 at 09:16
  • @einpoklum I saw your example used DCL + volatile. Though it is correct (wrt declaring it volatile ) I would rather use his latter example then the DCL. I find it to be more readable and less verbose. Lastly your example is wrong, you should be synchronizing on `Foo.class` and not the instance. – John Vint Apr 04 '13 at 12:10
  • I agree this is the best solution. It is [faster than the double-checked lock](http://literatejava.com/jvm/fastest-threadsafe-singleton-jvm/). It has less conceptual baggage than the Enum Way, and works in exactly the same way. ([Unless getInstance is the only static method, then use the OP's first code snippet.](http://stackoverflow.com/a/15793074/1048186)) – Josiah Yoder Jan 06 '16 at 15:46
10

You first design is actually lazy. Think about it, the instance is only created when the class is initialized; the class is only initialized when the getSingleton() method is called [1]. So the instance is only created when it's asked for, i.e. it's lazily created.

[1] http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
3

The second one is very bad in terms of readability, first one is suitable. Have a look at this article. Its about double check locking, but also will give you wide information about singletons multithreading.

Mikhail
  • 4,175
  • 15
  • 31
  • How is the second one *very bad*? – John Vint Apr 03 '13 at 16:13
  • It will work, but I do not see any use in FooLoader and if statement inside constructor. Let it be not bad but overburden. Remember other people will read your code. So keep it simple. – Mikhail Apr 03 '13 at 16:18
  • I agree, have the check in the constructor is not necessary and should be removed. But when talking about thread-safety I see absolutely nothing wrong with the second snippet of code. – John Vint Apr 03 '13 at 16:22
  • In both cases new instance is created while class initialization, so no difference. – Mikhail Apr 03 '13 at 16:26
  • That is not correct. Try it yourself. Have the constructor of the singleton type class do some println. Now have another static method do a different println method. If you were right, then you should see both printlns if you never invoke the `getInstance` and only invoke the other method that does a simple println – John Vint Apr 03 '13 at 16:47
1

The best way is actually to use the Enum Way:

public enum Singleton {
    INSTANCE;
    public void execute (String arg) {
            //... perform operation here ...
    }
}
Jean Logeart
  • 52,687
  • 11
  • 83
  • 118
1

In my opinion, this is an inappropriate pattern to use. It makes assumptions about the JVM's behavior which are non-trivial and confusing. Also, it has a dummy class. Dummy classes should be avoided when possible.

I suggest the straightforward approach:

public class Foo {
    private volatile static final Foo instance = null;

    private Foo() { }

    public static Foo instance() {
        if (instance == null) instance = new Foo();
        return instance;
        }
    }
}

... although, this does not work as-is - it's not thread safe.. What you really want is the double-check pattern presented in Item 71 of Bloch's Effective Java; see here. Adapting the example at the link to your case, we get:

public class Foo {
    private volatile static final Foo instance = null;

    private Foo() { }

    public static Foo instance() {
        if (instance != null) return instance;
        synchronized(instance) {
           Foo result = instance;
           if (instance == null) {
                result = instance = new Foo();
           return result;
        }
    }
}

Notes:

  • Don't worry about the performance of this code, modern JVMs take care of it and it's just fine. After all, premature optimization is the root of all evil.
  • As is suggested in other answers, the above is not Bloch's preferred solution, but I think using an enum for a singleton is semantically inappropriate just like what OP did originally.
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    If you aren't worried about performance, just use your first example and synchronize the whole method. Even simpler! – Josiah Yoder Jan 06 '16 at 15:16
  • 1
    For alternative versions of the double-lock, see https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java – Josiah Yoder Jan 06 '16 at 15:32