Some time ago the company some colleagues in the discussion of the singleton mode (I am the most slag of one, are not plugged in the mouth t__t), this mode uses the frequency is very high, may be many people most familiar with the design pattern, of course, the singleton mode is one of the simplest design patterns, simple to simple, but in the actual use of some pits.
PS: With the technology of interest in the same shoe plus group 5,446,459,721 Exchange
Total catalog of design patterns
Java/android design mode Learning Notes directory
features
Make sure that there is only one instance of a class, and instantiate it yourself and provide this instance to the entire system.
The singleton pattern is widely used, such as: Thread pool (threadpool), Cache, dialog, processing preferences, and Registry (registry) objects, log objects, objects that act as drivers for devices such as printers, graphics cards, and so on, and objects of these classes can only have one instance. If more than one instance is produced, it can lead to many problems, abnormal behavior of the program, excessive use of resources, or inconsistent results, so the main features of the singleton mode are as follows:
- The construction function is not open to the outside, generally private;
- Returns a singleton class object through a static method or enumeration;
- Ensure that the object of the Singleton class has only one, especially in the multi-threaded environment;
- Ensure that the object is not rebuilt when the Singleton class object is deserialized.
By privatizing a singleton class constructor, the client cannot manually construct an object of the Singleton class by using new. The Singleton class exposes a common static method that the client needs to obtain the unique object of the singleton class using this static method, and in the process of acquiring the singleton object, it is necessary to ensure thread safety, that is, the object of constructing the Singleton class in the multithreaded environment is also one and only, which is a key place in the singleton mode.
- Key Benefits
The main advantages of the singleton pattern are as follows:
- Singleton mode provides controlled access to a unique instance. Because the Singleton class encapsulates its only instance, it can tightly control how and when the customer accesses it.
- Because there is only one object in system memory, system resources can be saved, and for some object singleton patterns that need to be created and destroyed frequently, the performance of the system can be improved.
- Allows a variable number of instances. Based on the singleton pattern, we can extend the method to obtain the specified number of object instances by using a similar approach to single-instance control, which saves the system resources and solves the problem that the singleton objects share too much lossy performance.
- Main disadvantages
- Because there is no abstraction layer in the singleton pattern, the expansion of the Singleton class is very difficult.
- The responsibility of the Singleton class is too heavy, which violates the "single duty principle" to some extent. Because the Singleton class serves both as a factory role, provides a factory approach, and acts as a product role, it includes business methods that combine the creation of products with the functionality of the product itself.
- Many object-oriented languages, such as Java, C #, now run environments that provide automatic garbage collection, so if the instantiated shared object is not exploited for a long time, the system will consider it garbage, automatically destroy and reclaim the resources, and re-instantiate the next time it is exploited, which will result in the loss of the shared singleton state.
UML class Diagram
The class diagram is simple, the Singleton class has a static instance object, the type is Singleton, the constructor is private, a static function that provides a getinstance (), returns the instance object just now, and in that function the initial Start the operation.
Example and source code
The singleton pattern is a lot of writing, summed up:
lazy initialization, thread-unsafety (lazy method, thread insecure)
Lazy initialization, a lot of people called the Lazy method, writing at a glance, when needed to call the getinstance () function to get the unique static object of Singleton, if it is empty, will do an additional initialization operation.
publicclass Singleton { privatestaticnull; privateSingleton(){} publicstaticgetInstance() { ifnull) new Singleton(); return instance; }}
It is important to note that this type of writing is unsafe in multithreaded operations, and the consequence is that it is possible to produce multiple singleton objects, such as when two threads execute the getinstance () function at the same time, and then execute to the new operation, it is likely that two different objects will be created at the end.
lazy initialization, thread-safety, double-checked (lazy method, thread safe)
To be thread-safe, you need to make sure that only one thread can perform the operation of the new Singleton object at any moment, so add the Synchronized keyword to the getinstance () function, similar to the following:
publicstaticsynchronizedgetInstance() { ifnull) new Singleton(); return instance; }
But in the words "Head first", for the vast majority of situations where synchronization is not required, synchronized will make the function perform 100 times times worse (Since synchronizing a method could in some Extreme cases decrease performance by a factor of or higher), so there is a double-checked (double detection) method:
public class Singleton {private volatile static Singleton instance = null ; private singleton () {} public static Singleton getinstance () {if (Instance = = nul L ) {synchronized (singleton.class) {if (instance = = null ) {instance = new Singleton (); }}} return instance; }}
We assume that two threads, a, B, execute to the getinstance () method at the same time, the first if judgment, two threads are true at the same time, enter the IF statement, there is a synchronized synchronization, so then there is only one thread a will execute to synchronized Statement inside, and then again to determine whether instance is empty, to empty the new singleton object and assign a value to the INSTANCE,A thread exit Synchronized statement, hand over the synchronization lock, b thread into the synchronized statement inside, If the instance is determined to be empty, to prevent the creation of different instance objects, which is also the second if the role of the judgment, B thread discovery is not empty, so the end of A and B threads can get to the same singleton object, After the thread calls the getinstance () function, it will return directly because the instance is not empty and will not be affected by synchronized performance.
volatile keyword Introduction
The Double-checked method uses the volatile keyword, the role of the volatile keyword needs to be carefully introduced, in C + +, the role of the volatile keyword and Java is not the same, summed up:
The role of the volatile keyword in
- C + +
- visibility
visibility refers to the modification of the variable in a thread that is immediately written back to the main memory by the work memory Therefore, it is immediately reflected in the read operation of other threads. By the way, working memory and main memory can be approximately understood as the actual computer cache and primary storage, the working memory is the thread exclusive, main memory is thread-shared.
- non-optimal
"non-Optimized" attribute, volatile tells the compiler, do not make various radical optimization of my variable, or even directly eliminate the variable, to ensure that the programmer written in the code instructions, will be executed.
- sequential
"sequential", which guarantees the order of volatile variables, and the compiler does not perform chaos optimization. The order of volatile variables and non-volatile variables, the compiler does not guarantee the order, may be chaotic optimization. At the same time, C + + volatile keywords, and can not be used to build happens-before semantics, so in the multithreaded programming, be careful to use volatile, do not fall into the use of volatile variables in the trap.
- The volatile keyword action in Java
Java also supports the volatile keyword, but it is used for a different purpose. When volatile is used for a scope, Java guarantees the following:
- (for all Java versions) read and write a volatile variable with a global ordering. This means that each thread accesses a volatile scope and reads its current value before proceeding, rather than (possibly) using a cached value. (However, there is no guarantee that the relative order of read and write often reads and writes to volatile scopes, which is often not a useful thread build).
- (for Java5 and later versions) volatile reads and writes establish a happens-before relationship, similar to requesting and releasing a mutex [8].
using volatile is faster than using locks, but in some cases it does not work. The volatile use range has been extended in Java5, especially when double-check locking is now working correctly [9].
There is a detail above, the Java 5 version after the volatile read and write to establish a happens-before relationship, the previous version will have a problem: why is volatile used in this example of double Checked locking, the answer is clearly written, thread A will allocate memory to instance before fully constructing the instance object, and thread B can go back to using it when it sees that the instance has allocated memory not empty. So this causes the B thread to use the partially initialized instance object, and finally it will be a problem. Double-checked locking There's a word inside
Asof5.0hasvolatilenewisin [2and [3].
So for Android, using the volatile keyword is a bit of a problem.
Reference article :
Volatile variable
A deep anatomy of the C + + volatile keyword
The role and usage of volatile in Java
Eager initialization thread-safety (a hungry man method, thread safety)
The "A Hungry Man" method initializes the variable before it is used, which is thread-safe, of course, and is simple:
privatestaticnew Singleton();privateSingleton(){ "eager initialization thread-safety 1";}publicstaticgetInstance(){ return instance;}
Or
privatestatic Singleton instance null;privateSingleton(){ "eager initialization thread-safety 2";}static { new Singleton();}publicgetInstance(){ return instance;}
The code is simple, one is to initialize directly, and the other is to initialize with a static block, which is the object that is initialized when the class is loaded, regardless of whether the object is needed or not. The advantage of this writing is that it is easy to write and thread-safe, but at this point the initialization of instance obviously does not achieve the effect of lazy loading.
Static inner class thread-safety (statically internal class, thread safe)
Since the static inner class is initialized in use in Java, it is possible to use this innate lazy-loading feature to implement a simple, lazy-loading, thread-safe Singleton pattern:
private Static class singletonholder{private Span class= "Hljs-keyword" >static final Singleton instance = new Singleton ();} private singleton () {name = "Static inner class Thread-safety" ;} public static Singleton getinstance () {return singletonholder.instance;}
Defines a static inner class of Singletonholder that defines an external class Singleton static object, and initializes it directly, returning the object directly in the GetInstance () method of the external class Singleton. Since the use of static inner classes is a deferred loading mechanism, the Singletonholder class is loaded only when the thread calls to the getinstance () method, and the instance variable is initialized when the class is loaded, so this implements the deferred loading mechanism. It is also only initialized this time, so it is also thread-safe, and the wording is simple.
PS
All of the implementations mentioned above have two common drawbacks:
- Requires additional work (Serializable, transient, readresolve ()) to serialize, or a new instance is created each time a serialized object instance is deserialized.
- You might be forced to call our private constructor with reflection (if you want to avoid this, you can modify the constructor so that it throws an exception when creating the second instance).
enum (enum notation)
After JDK1.5, you can use enum to implement a singleton pattern by adding the enum attribute:
enum SingleEnum{ INSTANCE("enum singleton thread-safety"); private String name; SingleEnum(String name){ this.name = name; } publicgetName(){ return name; }}
The use of enumerations, in addition to thread-safe and anti-reflection forced invocation of the constructor, also provides an automatic serialization mechanism to prevent deserialization when a new object is created. Therefore, effective Java recommends using enumerations as much as possible to implement the singleton. Unfortunately, it is not recommended to use Enum in Android, primarily because the enumeration in Java is inherited from the Java.lang.Enum class, which invokes the initialization method to prepare each enumeration variable for the first call. Each enumerated item is declared as a static variable and is assigned a value. There is a problem with the actual use of Google's official documentation:
Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android
This blog also specifically calculates the size of the enum: Hu-the Price of ENUMs, so the drawbacks of enumeration notation are obvious.
Registration Type
A registered singleton actually maintains an instance of a set of singleton classes that are stored in a map (the register), returned directly from the map for an instance that has already been registered, and then registered and returned, if not registered.
//Similar to the method in spring, the class name registration, the next time from the inside to get directly. Public classSingleton {Private Staticmap<string,singleton> map =NewHashmap<string,singleton> ();Static{Singleton single =NewSingleton (); Map.put (Single.getclass (). GetName (), single); }//Protect the default construction child protected Singleton(){}//Static factory method to return such unique instances Public StaticSingletongetinstance(String name) {if(Name = =NULL{name = Singleton.class.getName (); System. out. println ("name = = NULL"+"--->name="+name); }if(Map.Get(name) = =NULL) {Try{Map.put (name, (Singleton) class.forname (name). newinstance ()); }Catch(Instantiationexception e) {E.printstacktrace (); }Catch(Illegalaccessexception e) {E.printstacktrace (); }Catch(ClassNotFoundException e) {E.printstacktrace (); } }returnMap.Get(name); }//A schematic business approach PublicString About() {return "Hello, I am Regsingleton."; } Public Static void Main(string[] args) {Singleton Single3 = singleton.getinstance (NULL); System. out. println (Single3.about ()); } }
In this way I am extremely rare, and in fact the internal implementation is also used in the A Hungry man-type singleton, because of the static method block, its singleton is instantiated when the class is loaded.
Summary
To sum up, usually in Android use double-checked or Singletonholder are can, after all, Android has long been not using the version of JDK5 before. Due to the multi-process mechanism in Android, it is not possible to create the same instance variable in different processes, just as the application class initializes two times.
But regardless of the approach, keep in mind the three main points of the single case:
- Thread Safety
- Lazy Loading
- Serialization and deserialization security
Source Download
Https://github.com/zhaozepeng/Design-Patterns
References
Http://www.tekbroaden.com/singleton-java.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source= Toutiao.io
http://hedengcheng.com/?p=725
Http://www.cnblogs.com/hxsyl/archive/2013/03/19/2969489.html
Http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html
http://blog.csdn.net/jason0539/article/details/23297037
Https://sourcemaking.com/design_patterns/singleton
Http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java
Http://stackoverflow.com/questions/15792186/singleton-pattern-with-combination-of-lazy-loading-and-thread-safety
Https://en.wikipedia.org/wiki/Singleton_pattern
Https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
Https://zh.wikipedia.org/wiki/Volatile%E5%8F%98%E9%87%8F
Http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
http://www.jianshu.com/p/d8bf5d08a147
http://preshing.com/20130702/the-happens-before-relation/
http://blog.csdn.net/imzoer/article/details/8620801
Java/android Design Patterns Learning notes (i)---singleton mode