1. Definition of a singleton pattern
The singleton pattern (Singleton Pattern) is a relatively simple pattern, and its original definition is as follows: ensure a class have only one instance, and provide a global point of access to it . That is, ensure that there is only one instance, and instantiate it yourself and provide this instance to the entire System. The general class of the singleton pattern is shown in the following example:
The Singleton class is called a singleton class by using the private constructor to ensure that only one instance is produced in an application and is instantiated by itself (in Singleton, its own new Singleton ()). The generic code for the singleton pattern is as follows (this is also known as the A Hungry man single-case):
/****************** Singleton mode: program Listing 1 ***************************/ public classSingleton {Private StaticSingleton instance =NewSingleton ();//1. Own internal new one PrivateSingleton () {//2. Private constructors to prevent instantiation } //3. Provide a public interface to return the object just new public StaticSingleton getinstance () {returninstance; } public voidTest () {System.out.println ("singleton"); } } /********************************************************************/
2. Thread safety problems in singleton mode
The above is a classic Single-mode program, and this program does not produce thread synchronization problems, because the class was first loaded when the initialization of Instance. however, There are other implementations of the Singleton pattern, and there is the possibility of thread synchronization problems, see the following example:
/** This approach is Non-thread-safe (lazy Singleton)*/ public classSingleton {Private StaticSingleton instance =NULL; PrivateSingleton () {} public StaticSingleton getinstance () {if(instance = =NULL) {instance=NewSingleton (); } returninstance; } }
Why is there a thread safety problem? If a thread a executes to instance = new Singleton (), but has not yet obtained the object (the initialization of the object takes time), the second thread B is also executing, execution to the judgment instance = = null, then thread B gets the condition is true, So also into the instantiation of the instance, and then thread A to get an object, thread B also obtained an object, in memory there are two of objects!
There are many ways to solve thread-safety problems, such as we can add the Synchronized keyword to the getinstance () method, as Follows:
public Static synchronized Singleton getinstance () { ifnull) { new Singleton (); } return instance; }
But the Synchronized keyword locks on the object, and this usage degrades in performance because the object is locked every time the getinstance () is Called. In fact, as long as the first time to create the object lock, after the creation of the end is not necessary, so we can make further improvements, as Follows:
public static Singleton getinstance () { if (instance = null synchronized (instance) { if (instance = null " {instance = new< /span> Singleton (); }}} return instance; }
We add the Synchronized keyword to the inside, that is, when the call is not required to lock, only when the instance = = NULL and create the object when the lock, this is better than the way Above. however, This approach is likely to cause thread safety issues, because the creation of objects and assignment operations in the JVM is performed separately, i.e. instance = new Singleton () is a two-step sentence. The process is this: the JVM allocates a blank memory to the singleton instance and assigns it to the instance member, but at this point the JVM does not start initializing the instance and then goes to the new singleton object to assign to Instance. This can lead to threading problems, such as a thread entering the synchronized code block, after executing instance = new Singleton () exit code block, But there is no real initialization, This is the thread B came in, found that instance is not null, So we immediately return to the instance (it is not initialized well), then B began to use the instance, but found not initialized, so there is a problem.
So to solve this "lazy" single-threaded problem, a proposal to use the above procedure in listing 1, that is, the use of "a hungry man-type" single Case. alternatively, in practice, an internal class can be used to maintain a singleton implementation. The mechanism inside the JVM guarantees that when a class is loaded, the loading process of the class is Thread-exclusive. thus, when we first call the getinstance () method, the JVM can help us ensure that the instance instance is created only once and that the memory assigned to instance is initialized, as shown in the following code:
/****************** Singleton mode: program Listing 2 ****************************/ public classSingleton {PrivateSingleton () {//Private constructor method to prevent instantiation } /*use an inner class to maintain a singleton*/ Private Static classSingletonfactory {Private StaticSingleton instance =NewSingleton (); } public StaticSingleton getinstance () {//Get Instance returnsingletonfactory.instance; } /*if the object is used for serialization, you can ensure that the object remains consistent before and after serialization*/ publicObject readresolve () {returngetinstance (); } } /********************************************************************/
3. Cloning of a singleton pattern
The above analysis of the single-instance mode of thread safety, There is a problem is to consider the Single-mode object replication Problem. In java, objects are not copied by default, but if the Cloneable interface is implemented and the Clone method is implemented, a new object can be created directly from the object copy, and the object copy is not the constructor of the calling class, so even if it is a private construction method, the object can still be Copied. however, in general, the Singleton class will rarely be actively asked to be replicated, so the best way to solve this problem is the Singleton class do not implement the Cloneable Interface.
4. Expansion of Singleton mode
If a class can produce multiple objects and the number is unrestricted, it is very easy to do so directly with NEW. But if you use singleton mode, but require a class to actually produce two or three objects? How is this possible? In this case, we need to maintain a variable in the Singleton class to represent the number of instances, and also need some containers to hold different instances and the corresponding properties of the instance, as Follows:
/*************************** single-instance mode extension: Listing 3 ************************************/ public classSingleton {//define the maximum number of instances that can be generated Private Static intMaxnumofinstance = 3; //store the name of each instance Private Staticarraylist<string> NameList =NewArraylist<string>(); //Store each instance object Private StaticArraylist<singleton> instancelist =NewArraylist<singleton>(); //index of the current instance Private Static intindexofinstance = 0; //static block of code that initializes 2 instances when the class is loaded Static { for(inti = 0; I < maxnumofinstance; i++) {instancelist.add (NewSingleton ("instance" + (i+1))); } } PrivateSingleton () {}PrivateSingleton (String Name) {//private constructor with parametersNamelist.add (name); } //returning an Instance object public StaticSingleton getinstance () {random Random=NewRandom (); //randomly pick an instanceIndexofinstance =Random.nextint (maxnumofinstance); returnInstancelist.get (indexofinstance); } public voidtest () {System.out.println (namelist.get (indexofinstance)); } } /******************************************************************************************/
Let's write a test program and see the Results:
public class singletontest { publicstaticvoid main (string[] Args) { int num = 5; for (int i = 0; i < num; i++) { = singleton.getinstance (); Instance.test (); }}}
This allows us to create a fixed number of instances using a singleton pattern. The test result output is as Follows:
Instance1 instance1 instance2 instance3 instance3
5. Advantages and disadvantages of singleton mode
Advantages:
1. There is only one instance in memory, all reduce the cost of the village, especially when an object needs to be created and destroyed frequently, and the performance can not be optimized when it is created or destroyed, the advantage of the singleton mode is very obvious;
2. Reduces the performance overhead of the system, when an object is generated that requires more resources, such as reading a configuration, generating a dependent object, you can create a singleton object directly at the time the app starts, and then permanently reside in Memory.
3. You can avoid multiple uses of resources, such as write file actions, because only one instance exists in memory, avoid simultaneous write operations to the same resource File.
4. The singleton mode can set global access points in the system, optimize and share resource access, for example, you can design a singleton class that is responsible for mapping all data tables.
Disadvantages:
1. The singleton mode has no interface, the extension is difficult, to extend, in addition to modify the code basically there is no second way to achieve
2. The singleton mode is not good for testing, in a parallel development environment, if the singleton mode is not completed, it cannot be tested.
6. Application Scenarios for Singleton mode
In a system that requires a class to have only one object, a singleton pattern can be used:
1. An environment that requires a unique serial number to be Generated.
2. The entire project requires a shared access point or shared data, such as the amount of traffic on a web page, which can be stored to the database without each refresh, but ensure that the singleton thread is Safe.
3. Creating an object requires too many resources to access resources such as IO and Databases.
4. You need to define a large number of static constants and static methods (such as tool classes) of the environment, you can use a singleton mode, of course, can also be directly declared as static Mode.
The singleton pattern is also used in spring, with each bean being a singleton by default, so the spring container can manage the lifetime of these beans, decide when to create them, when to destroy them, how to handle them when they are destroyed, and so On. If a Non-singleton mode (prototype Type) is used, the management of the Bean's initialization is given to the Java EE container, and the spring container is not tracking the lifetime of the Bean.
Java design mode singleton (Singleton) mode