Design Patterns in Android-singleton mode
Singleton mode is a more commonly used mode, in Java if you want to have only one instance of a class in a JVM, you need to use the singleton mode, and there is only one instance of the demand is generally because:
1, object instances are larger and more complex, and creation overhead is significant.
2, only one instance is needed to maintain the process and interaction of the entire function.
For example, when the phone app on Android starts, for capacity is single phone, only one phone object is created to manage objects such as Ril,calltracker,servicestatetracker, and no second phone object exists in the phone to communicate with RILC.
Class diagram
The class diagram of a single example is simple, it looks simple, only one instance of a class can be obtained, but I think the singleton is more complex than the other created patterns.
If you want to create a class singleton. Normally only new Singleton () is required, but if you want to have only one instance of Singleton, you cannot create it in this way, because every new instance will produce a fresh one:
1, in order to not use new creation, it is necessary to change the constructor to private;
2, in order to have only one instance, it is necessary to singleton itself to maintain the instance, so the class needs to define a singleton instance, obviously it should be private, because it is an instance of the class, not an instance of the object, so it should also be static;
3, because cannot new, in order to have the method to obtain the Singleton instance, must return the instance through a static method, for example public static Singleton getinstance (), inside if the instance is null the new, Otherwise, you can return instance.
Said so many things to pay attention to is still quite a lot of, according to the above analysis, has been able to create a simple singleton mode.
Common a hungry man single case mode
public class singleton { private static Singleton instance = new Singleton (); private singleton () {//nothing }public static Singleton getinstance () {return instance;} public void say () {System.out.println ( "I am Singleton" );}
The A hungry man Singleton is instantiated when the class is loaded. The advantage is that because of the classloder mechanism, it is guaranteed that when a class is loaded, the load of this class is mutually exclusive, while the static instance of the A hungry man Singleton creates a new instance directly, which can be safely obtained by thread when it is loaded. This avoids thread safety issues.
The disadvantage is that the instance will waste resources and time to instantiate when it is loaded. Although most of the time it is loaded when calling getinstance, there is no guarantee that other methods will be used to instance to create a new instance.
Lazy Load Singleton mode
This singleton Singleton class creates an instance when it is loaded, so it is set to NULL when it is used to create the object. Let it create a new instance in Getinstace, that is, lazy loading. This is also known as the lazy one-case.
Public class Lazysingleton {Private StaticLazysingleton instance =NULL;Private Lazysingleton() {//TODO auto-generated constructor stub} Public StaticLazysingletonGetinstace() {if(instance==NULL) {instance =NewLazysingleton ();}returninstance;} Public void say() {System.out.println ("I am Lazysingleton");}}
Lock single case mode
The
Lazy example in front of a single thread does not cause problems, but if you use it in a single thread, the problem occurs. If the AB two threads are going through getinstace to get an instance of the singleton, because there is no guarantee that the Getinstace method will execute another thread in one thread, and if all two threads determine the instance bit null, then it is possible to go into the new statement to create the instance.
in order to ensure that only one thread can execute getinstance at the same time, you need to lock the method, or use object locks inside the method, but be careful to place the lock on the outside of the if (instance = = null) judgment, or you may see a case where true is also determined.
publicclass SyncSingleton {privatestaticnull;privateSyncSingleton() {// TODO Auto-generated constructor stub}publicstaticsynchronizedgetInstance(){ifnullnew SyncSingleton();}return instance;}}
Or
Public class Syncsingleton { Private StaticSyncsingleton instance =NULL;Private Static FinalObject classlock = Syncsingleton.class;Private Syncsingleton(){} PublicSyncsingletongetinstance(){synchronized(Classlock) {if(Instance = =NULL) Instance =NewSyncsingleton ();returnInstance } } }
Double check and lock single case
The above problem solves the problem of multithreading, but also bring performance problems, because every call getinstance, will be synchronized, but in fact, if the instance instance has been established, then directly return to the instance instance is good, here is not locked, Only the case of the new instance requires a synchronous lock, but it is also said that the new time to put the lock on the IF (instance = = null) judgment outside, or else may appear at the same time to determine the true condition. So we have the following double-checked single-case pattern.
Public class Effectivesingleton { Private volatile StaticEffectivesingleton instance =NULL;Private Effectivesingleton() {//TODO auto-generated constructor stub} Public StaticEffectivesingletongetinstance() {if(Instance = =NULL) {//First determine if an instance has been created, if it has been created, directly returned, high efficiency synchronized(Effectivesingleton.class) {//If not created, then synchronized, and then initialized within the synchronization block. Note to determine again whether or not an instantiation has been instantiated if(Instance = =NULL) {instance =NewEffectivesingleton (); } } }returnInstance }}
This way, when the instance initialization is complete, each time getinstance is returned directly, no synchronization lock is required.
When you first call getinstance, the code portion of the synchronized block package guarantees that the new instance will not be called more than once.
The second if (instance = = NULL) condition is judged for the first if (instance = = NULL) is used for cases where an instance is already present, and the AB thread may be judged by the first condition. This needs to be within the synchronization block, must have a condition to judge.
Double check and lock single-case mode is a good solution to the performance problem of locking single case.
Using singleton mode for static inner classes
The
Static inner class is also called a nested class, which is more visually defined by the name. This means that the relationship between the inner class and the outer class is only a hierarchical nesting relationship, so the class file name is just as follows when creating the class files: Outer$inner.java, which is exactly the same as two ordinary classes in terms of usage.
on the basis of a hungry man single case, instance = new Singleton () for external use of a static inner class called Singletonholder.
This will not cause static internal class Singletonholder to load even when the singleton class is loaded, but only when the singletonholder is used. The
also guarantees thread safety when creating an instance due to the mutex of the mechanism of the class's loading.
class Singleton { privatestaticclass SingletonHolder { privatestaticfinalnew Singleton(); } privateSingleton() { } publicstaticfinalgetInstance() { return SingletonHolder.instance; }}
Single case in Android
To create an example of a phone object through Phonefactory, the interception section is as follows:
Public class phonefactory { Static PrivatePhone Sproxyphone =NULL; ...... Public Static void Makedefaultphone(Context context) {synchronized(Phone.class) {if(!smadedefaults) {... sproxyphone =NewPhoneProxy (NewGsmphone (context, Scommandsinterface, sphonenotifier)); ... Smadedefaults =true; } } }
It can be seen that this example conforms to the lock singleton pattern above, although it is not a double-judging way to increase efficiency, but because Phonefactory's makedefaultphone basically does not have multi-threading usage, it is called only when the phone app is started.
and phonefactory through Makedefaultphone to create an instance, but use Getdefaultphone to get the instance, there is no instance of the case already exists, but also into the synchronization block to determine the situation.
Design Patterns in Android-singleton mode