(Singleton Pattern)
(Singleton Pattern)
Make sure that there is absolutely only one instance of a class in any case, and that a global access point is provided。Sometimes it takes too much time or too much to create an object, but we use it a lot. We can use the singleton pattern, and if a utility class has state, we also need a singleton, because if it is multiple instances, there may be data reading errors, such as configuration classes, we need a singleton of it, you can go to one place to get it, you don't need multiple creations. Common way to write
it
- Hungry singleton
- Slob-style singletons
- Registered singletons
- Threadlocal Singleton
To explain some terms
High execution efficiency:
- classes is created ,When classes are been loading, if we want to get it just getting it and without to create it again
Thread safety:
- caused by the calsses that you want are already created,if you do not create it again, it is thread safety,isn't it!
- there are no situation that two threads get an one method that you use to creat classes.
Waste of memory:
- who can sure that the calsses are uesd certainly?
- if you don't use these classes, which means these are occupying memory.
Eager Singleton
public class HungrySingleton { private static final HungrySingleton hungrySingleton = new HungrySingleton();</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> HungrySingleton() { } </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> HungrySingleton getInstance() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> hungrySingleton; }
}
advantages:1.High execution efficiency 2.Thread safety
disadvantages:1.Waste of memory
To solve the problem of Waste of memory. . . .
Lazy Singleton
public class LazySimpleSingleton { private static LazySimpleSingleton lazySimpleSingleton;</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> LazySimpleSingleton() { } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> static LazySimpleSingleton getInstance() { </span><span style="color: #0000ff;">if</span> (lazySimpleSingleton != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { lazySimpleSingleton </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> LazySimpleSingleton(); } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> lazySimpleSingleton; }
}
To test
public class ExecuteThread implements Runnable { public void run() { LazySimpleSingleton lazySimpleSingleton=LazySimpleSingleton.getInstance(); System.out.println(Thread.currentThread().getName() + ":" + lazySimpleSingleton); } } public class LazySimpleSingletonTest { public static void main(String[] args) { Thread thread=new Thread(new ExecuteThread()); Thread thread2=new Thread(new ExecuteThread()); thread.start(); thread2.start(); } }
result:
Actually,Sometimes it produces the same results, sometimes it doesn't,which shows There are problem of security of Thread!
same results:
- normal execution sequence
The latter covers the former(2 Threads execute the same code,the former assign the classes but did not return,at this time,the latter began to execute,so latter covers the former.in fact, there are two classes were created )
different results:
- 2 Threads execute the same code,the former have returned,the the latter returned
tips: the red one is what i said the same code executed
if (lazySimpleSingleton != null) { lazySimpleSingleton = new LazySimpleSingleton(); }
advantages: Save memory
disadvantages: Thread unsafe
To solve the problem of Thread of unsafe. . . . (easily,To put a key word of synchronized in front of "static LazySimpleSingleton" like ->(
public synchronized static LazySimpleSingleton getInstance())
),but cause a problem that all of the others threads are waiting, the picture below shows that if one thread get a source,which means others can not get the same source,all others will be blocked,in this way,all of others will be waiting and one by one to execute
To solve the problem of performance--------------------------->
public class LazyDoubleCheckSingleton { private static LazyDoubleCheckSingleton lazySimpleSingleton;</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> LazyDoubleCheckSingleton() { } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> LazyDoubleCheckSingleton getInstance() { </span><span style="color: #008000;">//</span><span style="color: #008000;"> To check whether we should to create or not,if already the class is create, the left of others do not need to execute code below(solve problem of performance)</span> <span style="color: #0000ff;">if</span> (lazySimpleSingleton == <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">synchronized</span> (LazyDoubleCheckSingleton.<span style="color: #0000ff;">class</span><span style="color: #000000;">) { </span><span style="color: #008000;">//</span><span style="color: #008000;"> if two threads enter into, what should we do,so Let's make a judgment here</span> <span style="color: #0000ff;">if</span> (lazySimpleSingleton == <span style="color: #0000ff;">null</span><span style="color: #000000;">) { lazySimpleSingleton </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> LazyDoubleCheckSingleton(); } } } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> lazySimpleSingleton; }
}
To explain:
first of all,all threads can be allowed to enter into the method, and if lazySimpleSingleton == null the threads can enter into(solve the problem of performance->do not need to wait), then to use 'synchronized ' to limit problem of Thread unsafe,but if more than one thread enter into and one of these has executed into ending of block of 'if', definitely, the other still will created,so we make a judgement again(resolve the problem of thread unsafe )
but !!! the method will not be elegant enough.. it is hard to read,and produce problem 'Tag and Seek',so we add 'volatile' in front of 'static LazyDoubleCheckSingleton' like
private volatile static LazyDoubleCheckSingleton lazySimpleSingleton;
To solve the problem of not enough elegant--------------------------->
public class LazyStaticInnerClassSingleton { public LazyStaticInnerClassSingleton() { // what it is essential to creating the class is to use Constructor to create // so if someone wants to use Constructor to create,we just throw Exception to avoid illegal create throw new RuntimeException("forbid to create...."); }</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> LazyStaticInnerClassSingleton getInstance() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> LazyHolder.lazyStaticInnerClassSingleton; } </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> LazyHolder { </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> LazyStaticInnerClassSingleton lazyStaticInnerClassSingleton = <span style="color: #0000ff;">new</span><span style="color: #000000;"> LazyStaticInnerClassSingleton(); }
}
To explain:
apparently!we use mechanism of class loading,it is well known that during the classess the inner classess are not loaded,when we get the inner class that we want,than the inner class that we want will be load! but all of methods above will be destory by reflect!! what the essence that to use the reflect to create the classess is to use Constructor!so we just need to throw new RuntimeException in Constructor to avoid illegal create , but what i do still not enough decent,who konw the reason why we thrown an exception at the Constructor?
To solve the problem of not enough decent--------------------------->
Register Singleton(container Singleton)
public enum EnumSingleton { INSTANCE;</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object getData() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> data; } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setData(Object data) { </span><span style="color: #0000ff;">this</span>.data =<span style="color: #000000;"> data; } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object data; </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> EnumSingleton getInstance(){ </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> INSTANCE; }
}
public class User {
private String userName;
}
To Test
public class EnumSingletonTest { public static void main(String[] args) { EnumSingleton instance = EnumSingleton.getInstance(); instance.setData(new User()); Class<EnumSingleton> enumSingletonClass = EnumSingleton.class; try { Constructor<EnumSingleton> constructor = enumSingletonClass.getDeclaredConstructor(String.class,int.class); constructor.setAccessible(true); EnumSingleton enumSingleton = constructor.newInstance(); System.out.println(enumSingleton); } catch (Exception e) { e.printStackTrace(); } } }
To explain:
the image illustrate that we are not able to create a class with reflection
we find the class of Constructor has wrote ' if the modifier is emum than the class can not be create'
but, why we say that the method must be Thread safety,we still can skim the souce code->(Enum#valueOf),as soon as we create the Enum the 'INSTANCE ' will be put in the container,so Thread safety
so, in some extent , it will produce a new problem of Waste of memory,(put these INSTANCE into container in advance)
To solve the problem of not Waste of memory---------------------------> (we can simluate do it as what IOC does)
public class ContainerSingleton {ContainerSingleton() { } </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> Map<String, Object> iocMock = <span style="color: #0000ff;">new</span> ConcurrentHashMap<String, Object><span style="color: #000000;">(); </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> Object getInstance(String className) { Object instance </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">iocMock.containsKey(className)) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { instance </span>=<span style="color: #000000;"> Class.forName(className).newInstance(); iocMock.put(className, instance); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { e.printStackTrace(); } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> instance; } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> iocMock.get(className); }
}
public class Pojo {
String mock;
}
To test
public class ContainerSingletonTest { public static void main(String[] args) { Object pojo = ContainerSingleton.getInstance("Pojo"); Object pojo1 = ContainerSingleton.getInstance("Pojo"); System.out.println(pojo==pojo1); } }
actually, serialization can destory singleton!!!!!
To solve the problem of destruction the singleton with serialization --------------------------->
public class SerializableSingleton implements Serializable { final static SerializableSingleton INSTANCE = new SerializableSingleton();</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> SerializableSingleton() { } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> SerializableSingleton getInstance() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> INSTANCE; } </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Object readResolve() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> INSTANCE; }
}
To test
public class SerializableSingletonTest { public static void main(String[] args) {SerializableSingleton s1 </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; SerializableSingleton s2 </span>=<span style="color: #000000;"> SerializableSingleton.getInstance(); FileOutputStream fos </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { fos </span>= <span style="color: #0000ff;">new</span> FileOutputStream("D:\\growingup\\growup\\target\\SerializableSingleton.obj"<span style="color: #000000;">); ObjectOutputStream oos </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ObjectOutputStream(fos); </span><span style="color: #008000;">//</span><span style="color: #008000;"> output the file into disk</span>
oos.writeObject(s2);
oos.flush();
oos.close();</span><span style="color: #008000;">//</span><span style="color: #008000;">input the file in disk into memory</span> FileInputStream fis = <span style="color: #0000ff;">new</span> FileInputStream("D:\\growingup\\growup\\target\\SerializableSingleton.obj"<span style="color: #000000;">); ObjectInputStream ois </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ObjectInputStream(fis); s1 </span>=<span style="color: #000000;"> (SerializableSingleton)ois.readObject(); ois.close(); System.out.println(s1); System.out.println(s2); System.out.println(s1 </span>==<span style="color: #000000;"> s2); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { e.printStackTrace(); } }
}
To explain:
first we output the file into disk and input the file in disk into memory again,the result is true(still is a same class)the key is #readResolve,we still skim the souce of code(code java.io.ObjectInputStream#readObject0
after we have read can get that information of there is a judgment if you have a method named readResolve then to get with reflection, otherwise,to create a new instance.so we must be set a method called readResolve,which can help us to resolve problem of serialization with souce of code of java.lang.ClassNotFoundException
The last pattern of singleton i give
Threadlocal pattern of singleton(be ensure globally unique in the same Thread )
public class ThreadLocalSingleton { static final ThreadLocal<ThreadLocalSingleton> threadLocalSingletonThreadLocal = new ThreadLocal<ThreadLocalSingleton>() { @Override protected ThreadLocalSingleton initialValue() { return new ThreadLocalSingleton(); } };</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> ThreadLocalSingleton() { } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> ThreadLocalSingleton getInstance() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> threadLocalSingletonThreadLocal.get(); }
}
public class ExecuteThreadLocal implements Runnable {
public void run() {
ThreadLocalSingleton threadLocalSingleton=ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + threadLocalSingleton);
}
}
To test
public class ThreadLocalSingletonTest { public static void main(String[] args) { System.out.println(ThreadLocalSingleton.getInstance()); System.out.println(ThreadLocalSingleton.getInstance()); System.out.println(ThreadLocalSingleton.getInstance());Thread thread</span>=<span style="color: #0000ff;">new</span> Thread(<span style="color: #0000ff;">new</span><span style="color: #000000;"> ExecuteThreadLocal()); Thread thread2</span>=<span style="color: #0000ff;">new</span> Thread(<span style="color: #0000ff;">new</span><span style="color: #000000;"> ExecuteThreadLocal()); thread.start(); thread2.start(); }
}
To explain
the image above shows there are different threads get different results,but we can get a same instance in same thread,example is main thread(we get the same result in 3 times),we can find reason with resource of code of java.lang.ThreadLocal#get.
Store on a per-thread basis
practical application in souce of code
- org.springframework.beans.factory.config.AbstractFactoryBean#getObject
- org.apache.ibatis.executor.ErrorContext#instance
Sum up
advantages:
- ther is just one instance in memory,which is efficient to diminish Memory overhead
- Access is effectively controlled
disasvantages:
there is no interface,so that it is difficult to expand(if we want to extend function,we have to modify original code)