As a program ape this particular species, have mastered a special ability is the programming idea, logic is more cautious, but sometimes always ignore some details, such as me, always feel that Singleton
is the simplest design patterns, do not care too much, but because this is not intended to be a disadvantage in development. Really too Young and simple.
No nonsense, straight into the subject.
In the Code of the world found there are various forms of the single case, some people say that there are 5 kinds of single cases, 6 kinds, 7 kinds ...
For the classification of the singleton this must be regulated, first of all, so many classifications are defined by what, what is the benchmark? Otherwise, there are so many ways to do it.
Thus summed down, from 延迟加载
执行效率
the point of view and the main is divided into two, a hungry man as the name implies is the implementation of high efficiency, but lack of delay loading, other writing is almost a lazy type of an extension, or optimization evolved, see the code below.
Common examples in development--a hungry man
publicclass SingletonDemo1 { privatestaticfinalnew SingletonDemo1(); publicstaticgetInstance() { return s1; } privateSingletonDemo1() { }}
Yes, that's right. The above code is called 单例-饿汉式
, a hungry man style has been high efficiency and is known in the single case, so the development of the common Singleton model will choose him, simple and useful.
>
Development evaluation: ★★★★☆
Delay Loading: ★☆☆☆☆
Execution efficiency: ★★★★★
Time-consuming snail-the lazy type
publicclass SingletonDemo2 { privatestatic SingletonDemo2 s1; publicstaticsynchronizedgetInstance() { ifnull) { new SingletonDemo2(); } return s1; } privateSingletonDemo2() { }}
In hello world
This world, we all know that this kind of singleton is basically not going to be used,
Double check lock-a hungry man type
This can be said to be a microcosm of the above a hungry man style, why so to say, because he is not perfect, still have bugs.
Public class SingletonDemo3 { Private StaticSingletonDemo3 S1; Public StaticSingletonDemo3getinstance() {if(S1 = =NULL) {//The temporary variable is used hereSingletonDemo3 instance;synchronized(Singletondemo3.class) {instance = S1;if(Instance = =NULL) {synchronized(Singletondemo3.class) {if(Instance = =NULL) {instance =NewSingletonDemo3 (); }} S1 = instance; } } }returnS1; }}
This approach is mainly through if to determine non-null instances, improve the efficiency of execution, do not have getInstace
to synchronize every time, as long as the first time to synchronize, there is no need to create.
But why is there a bug in this writing? This problem is mainly caused by the internal model of the JVM layer in Java. The simple point is that instance引用的对象有可能还没有完成初始化完就直接返回该实例过去
after the jdk1.5 the problem has been optimized, it is not much to say, you can see this blog is good.
See details
There are, of course, some solutions.
- Using the volatile keyword to resolve a double-check lock bug, the volatile keyword is another scenario in Java that addresses visibility and ordering issues.
Public class safedoublecheckedlocking {//Added volatile keyword Private volatile StaticInstance Instance; Public StaticInstancegetinstance() {if(Instance = =NULL) {synchronized(Safedoublecheckedlocking.class) {if(Instance = =NULL) Instance =NewInstance ();//instance is volatile, it's no problem now.} }returnInstance }}
>
Development evaluation: ★★★☆☆
Delay Loading: ★★★☆☆
Execution efficiency: ★★★☆☆
Recommended static inner class-A hungry man type
Public class SingletonDemo4 { //Instantiate an object by means of a static inner class Private Static class Innersingleton { Private Static FinalSingletonDemo4 instance =NewSingletonDemo4 (); } Public StaticSingletonDemo4getinstance() {returnInnersingleton.instance; }Private SingletonDemo4() { }}
This week is a way to take advantage of some of the characteristics of class loading, in the Classloder mechanism, there is only one thread initialized instance, and this way there is the effect of delay loading, when it SingletonDemo4
is loaded, but the inner class InnerSingleton
is not loaded, because InnerSingleton
no active use, only the class is loaded by invoking the getInstance
method InnerSingleton
, and the instance private static final SingletonDemo4 instance = new SingletonDemo4();
So this ingenious way is safer and more efficient than a double-check lock.
>
Development evaluation: ★★★★☆
Delay Loading: ★★★★☆
Execution efficiency: ★★★★☆
Recommended enumeration-A hungry man type
publicenum SingletonDemo5 { //枚举元素本身就是一个单例(名字可以随意定义); INSTANCE; //可以做一些单例的初始化操作 publicvoidsingletonOperation() { }}
This way is actually very handsome, but in the actual development of very few people used, this is a bit strange, the first enum itself is a singleton, and the enumeration has a feature, you can avoid the serialization and reflection to solve single-case problems, the manager no longer worry about single security, may be 1.5 only enum reason it, If the project is appropriate, you can try this single example.
>
Development evaluation: ★★★★☆
Delay Loading: ★★★★☆
Execution efficiency: ★★★★☆
To summarize:
For each of the following examples, each has its own advantages, and which of these can be selected according to your business needs.
- A Hungry man
- Standard A Hungry man (Safety protection aspect enumeration single example better than standard a hungry man)
Thread-safe, efficient and lazy to load
- Enumeration single Example
thread safe, efficient and lazy to load (natural avoidance of reflection and deserialization)
?
- Lazy (Static inner class of efficiency is better than standard idler)
- Standard lazy
thread safe, inefficient, lazy to load
- Double detection (not recommended, bug)
thread safe, inefficient, lazy to load
- Static Inner class
thread safe, inefficient, lazy to load
?
In Java, are you sure you have a pair of singleton?