java - singleton pattern
DESCRIPTION
Another talk I gave at FastConnect, on the proper implementation of the Singleton Pattern in Java. Note : this talk was done prior to the release of Java 8TRANSCRIPT
The Singleton Pattern…because we all use it but…
Singleton Pattern
Singleton Pattern
1 & 1 instance
universal access
prevents/controlsconcurrency
Singleton Pattern
logging
databaseaccess
class loaders
factories
Basic Singleton
Basic Singleton
no new
utility method
static method
static instance
Basic Singleton
// Minimal Singleton (or is it ?), can’t handle pre-conditionspublic class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {if (INSTANCE != null) {
throw new IllegalStateException("Woops, the matrix is broken");}
}
public static Singleton getInstance() {return INSTANCE;
} }
Basic Singleton
// Same as before, can handle pre-conditions through static init. blockpublic class Singleton {
private static Singleton INSTANCE;
static {try {
INSTANCE = new Singleton();} catch (Exception ex) {
throw new RuntimeException("A damn error occured!", ex);}
}
private Singleton() {// Same as before
}public static Singleton getInstance() {
return INSTANCE;}
}
Broken Idioms
Broken IdiomsInstance not initialized, no sync
// Seems right, at first, but what about concurrency ?public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {// Nothing
}
public static Singleton getInstance() {if (INSTANCE == null) {
INSTANCE = new Singleton();}return INSTANCE;
}}
Broken IdiomsSynchronized getInstance()
// Concurrency issue fixed, but very slowpublic class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {// Nothing
}
public static synchronized Singleton getInstance() {if (INSTANCE == null) {
INSTANCE = new Singleton();}return INSTANCE;
}}
Broken IdiomsDouble checked locking
// Does not work this way, broken due to compiler re-orderingpublic class Singleton {
private static Singleton INSTANCE = null;
private Singleton() { }
public static Singleton getInstance() {if (INSTANCE == null) {
synchronized (Singleton.class) {if (INSTANCE == null) {
INSTANCE = new Singleton();}
}}return INSTANCE;
}}
Basic Singleton 2
Basic Singleton 2The Holder, proposed by Bill Pugh
//No language construct, relies on JVM memory model properties, very lazypublic class Singleton {
private Singleton() {// Nothing
}
// Loaded on the 1st exec of Singleton.getInstance(), not beforeprivate static class SingletonHolder {
public static final Singleton INSTANCE = new Singleton();}
public static Singleton getInstance() {return SingletonHolder.INSTANCE;
}}
Enum Singleton
Enum Singletonhave
methods
can implements
interface
static instances
free
thread safe*
* only if there is no
state
serializable
Enum SingletonProposed by Joshua Bloch
// OK in most cases, can be hacked by malicious serialized formpublic enum Elvis implements Singer, Zombie {
ELVIS;
@Overridepublic void singASong() {
// …}
@Overridepublic void eatBrains() {
// …}
}
SerializableSingleton
Enum Singleton
NO STATE
SerializableSingletonPart 1
public class Elvis implements Serializable {private static final Elvis INSTANCE = new Elvis();private static final long serialVersionUID = 42L;private volatile String[] songs = {"Hound Dog", "Heartbreak Hotel"};
public static Elvis getInstance() { return INSTANCE; }private Elvis() { }
public void leaveTheBuilding() { }
public void setFavouriteSongs(String[] songs) {this.songs = songs.clone();
}
public void printFavorites() {System.out.println(Arrays.toString(songs));
}
SerializableSingletonPart 2
// this should never be invokedprivate Object readResolve() {
return INSTANCE;}
private void readObject(ObjectInputStream ex) throws IOException {throw new InvalidObjectException("Cannot load another Elvis");
}
private Object writeReplace() {return new ElvisSerializableForm(songs);
}
SerializableSingletonPart 3
private Object writeReplace() {return new ElvisSerializableForm(songs);
}
private static class ElvisSerializableForm implements Serializable {
private final String[] songs;
public ElvisSerializableForm(String[] favoriteSongs) {this.songs = favoriteSongs;
}
public Object readResolve() {Elvis.INSTANCE.setFavouriteSongs(songs);return Elvis.INSTANCE;
}}
}
Singletons are Armful
Singletons are Armful
global state
hard to test
hard codeddependencies
Similar to Village of the
Damned
design anti-pattern
Might be OK if there is NO
STATE
use IoC for factories
Singletons
Singletons
Use enums
Use « Lazy Holders »
Beware of Serialization
Singleton are Armful
Don’t use them
Singletons
QuizzFixing the broken ones
A double fixFixing double checked locking
// Does not work this way, broken due to compiler re-orderingpublic class Singleton {
private static Singleton INSTANCE = null;
private Singleton() { }
public static Singleton getInstance() {if (INSTANCE == null) {
synchronized (Singleton.class) {if (INSTANCE == null) {
INSTANCE = new Singleton();}
}}return INSTANCE;
}}
A double fixFixing double checked locking
// The right word, at the right time, in the right place can make a differencepublic class Singleton {
private static volatile Singleton INSTANCE = null;
private Singleton() { }
public static Singleton getInstance() {if (INSTANCE == null) {
synchronized (Singleton.class) {if (INSTANCE == null) {
INSTANCE = new Singleton();}
}}return INSTANCE;
}}
Biblio
Biblio
Bloch, Joshua. Effective Java, Second Edition. O’Reilly, 2008
Croisier, Olivier. De la bonne implémentation du Singleton en Java. 2008. http://thecodersbreakfast.net/index.php?post/2008/02/25/26-de-la-bonne-implementation-du-singleton-en-java
Hevery, Miško. Root Cause of Singletons, 2008. http://misko.hevery.com/2008/08/25/root-cause-of-singletons/
Hevery, Miško. Singleton are Pathlogical Liars, 2008. http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
Biblio
Hevery, Miško. Where Have All the Singletons Gone ?, 2008. http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/
Kabutz, Heinz. The Java Specialists’ Newsletter #163, 2008. http://www.javaspecialists.eu/archive/Issue163.html
Manson, Jeremy. Double Checked Locking, 2008. http://jeremymanson.blogspot.fr/2008/05/double-checked-locking.html
Pugh, Bill. The « Double-Checked Locking is Broken » Declaration. http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Biblio
Pugh, Bill. The Java Memory Model, 2004. http://www.cs.umd.edu/~pugh/java/memoryModel/
Pugh, Bill. JSR 133 (Java Memory Model) FAQ, 2004. http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
Wikipedia, Initialization-on-demand holder idiom. http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
Wikipedia, Singleton pattern. http://en.wikipedia.org/wiki/Singleton_pattern