Implementation methods of Singleton Mode

Source: Internet
Author: User

The Singleton mode is one of the most common today. It is an object creation mode used to produce a specific instance of an object. It ensures that only one instance is generated for a class in a system. In Java, such behavior brings two benefits:

1): For frequently created objects, the time spent on Object creation can be omitted. For some heavyweight objects, this is a very considerable system overhead.
2): Due to the reduction of new operations, the usage frequency of the system memory will also be reduced, which will reduce the GC pressure and shorten the GC pause time.

Therefore, the singleton mode can effectively improve system performance for key components and frequently used objects of the system.
The following describes how to write several Singleton modes:

1. Hunger Mode
Public Singleton {private Singleton {system. out. println ("Singleton is create") // the process of creating a singleton instance may be slow.} Private Static Singleton instance = new Singleton (); public static Singleton getinstance () {return instance ;}}

This is the most common method that is easy to understand. Pay attention to the highlighted part in the Code. First, you must have a private access-level constructor for the Singleton. Only in this way can we ensure that it will not be instantiated in other code in the system. This is very important. Second, the instance member variable and the getinstance () method must be static. You can use singleton. getinstance () to obtain the related Singleton (when the class is loaded, the instance object is created in the static memory zone and there is only one copy. Note that the static method is independent from any instance. Therefore, the static method must be implemented rather than abstract. In addition, because instance members are associated with specific objects, only static member variables and member methods of the class can be accessed .).

However, its shortcomings are also obvious, that is, it cannot perform delayed loading on the instance. If the process of creating a single instance is slow and the instance member variable is defined as static, the single instance object will be created in the static memory zone when the JVM loads the single instance class. If this Singleton still plays other roles in the system (that is, other static methods or variables are used), The Singleton variable instance will be initialized when this Singleton class is used, whether or not it will be used (that is, any Singleton. during otherstaticmethod (), the constructor outputs "Singleton is create", causing unnecessary time and memory overhead ). To solve this problem, we need to introduce a delayed loading mechanism, which is the lazy mode below.

2. Lazy Mode
Public lazysingleton {private lazysingleton {system. out. println ("lazysingleton is create") // the process of creating a singleton may be slow.} Private Static lazysingleton instance = NULL; public static lazysingleton getinstancenotsafe () {// thread unsafe if (instance = NULL) {instance = new lazysingleton;} return instance;} public static synchronized lazysingleton getinstancesafe () {// thread security if (instance = NULL) {instance = new lazysingleton;} return instance ;}}

First, assign null to the initial value of the static variable instance to ensure that no additional load is required when the class is loaded. In the getinstance factory method, determine whether the current Singleton exists. If yes, the system creates a singleton if no Singleton exists. Note that in the preceding example, the getinstancenodsafe () method is not synchronous. Therefore, when thread 1 creates a new Singleton in a multi-threaded environment, the value assignment is completed. At this time, thread 2 determines that the instance is null, therefore, thread 2 will also create a singleton program, resulting in the creation of multiple instances rather than Singleton. Therefore, the getinstancesafe () method that introduces the synchronization keyword is used in a multi-threaded environment, but because synchronization needs to wait for it, the consumption is much higher than that in the hungry mode.

The following test code illustrates the problem:
    public void run() {        for(int i = 0 ;i < 100000 ;i++) {            Singleton.getInstance();            //LazySingleton.getInstanceSafe();        }        System.out.println("spent:" + (System.currentTimeMillis() - begintime));    }

When the preceding code is enabled for five threads at the same time, it takes 0 ms for a single case in the hungry Chinese mode, while lazysingleton takes about 390 Ms. The performance differs by at least two orders of magnitude. In order to delay loading, the synchronization keyword is introduced to reduce the performance, so as to make this synchronization method more effective, a dual check lock mode emerged.


3. Double check lock mode
Public Singleton {private Singleton {system. out. println ("Singleton is create") // the process of creating a singleton instance may be slow.} Private Static Singleton instance = NULL; public static Singleton getinstance () {If (instance = NULL) {synchronized (Singleton. class) {If (instance = NULL) {instance = new Singleton () ;}} return instance ;}}

This mode checks whether the instance is null before entering the synchronization statement. When the first thread 1 and the second thread 2 concurrently enter the first if statement, one thread enters the synchronized block to initialize the instance, and the other thread is blocked. When the first thread exits the synchronized block, wait for thread 2 to enter and check whether the instance has been created before returning the instance. So far, the instance has been checked twice. This is also the origin of the "double check lock" name. Compared with the lazy mode, you don't have to pay the synchronization cost every time you call getinstance (). Only the first creation will be synchronized, and it will be useless after creation.

4. static internal class mode
Public class staticinnerclasssingleton {private staticinnerclasssingleton () {system. out. println ("staticinnerclasssingleton is create");} Private Static class singletonholder {Private Static staticinnerclasssingleton instance = new staticinnerclasssingleton (); // only one instance will be loaded once} public static staticinnerclasssingleton getinstance () {return singletonholder. instance ;}
}
In this implementation, the singleton mode internal class is used to maintain the singleton instance. When staticinnerclasssingleton is loaded, its internal classes will not be initialized. Therefore, the staticinnerclasssingleton class will not initialize the singleton class when it is loaded into the JVM. When the getinstance () method is called, will load singletonholder, and then initialize. At the same time, because the instance is created when the internal class is loaded, it is naturally friendly to multithreading. The getinstance () method does not need to use synchronization keywords either. Therefore, you do not have to worry about creating a singleton if you only want to call other static methods.

5. Summary and vulnerability repair

Generally, the preceding method can ensure that only the unique instance exists in the system. For personal comparison, we recommend the third or fourth method. However, there are still exceptions, which may cause the system to generate multiple instances. For example, in the Code, the system uses the reflection mechanism to forcibly call the private constructor of the singleton class to generate multiple Singleton instances, however, we will not discuss this extreme approach here. However, some valid methods may lead to the generation of multiple Singleton instances, such:

1. If a singleton is loaded by different classloaders, there may be multiple Singleton instances. It is assumed that it is not a remote access. For example, some servlet containers use different class loaders for each servlet. In this way, if two servlets access a singleton class, they will all have their own instances.
2. If Singleton implements the java. Io. serializable interface, the instances of this class may be serialized and restored. In any case, if you serialize an object of the singleton class and restore multiple objects, you will have instances of multiple Singleton classes.

Solution to the first problem:
private static Class getClass(String classname) throws ClassNotFoundException {         
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if(classLoader == null){    classLoader = Singleton.class.getClassLoader();   }
return (classLoader.loadClass(classname));
} }
Solution to the second problem:
Public class Singleton implements java. Io. serializable {
Public static Singleton instance = new Singleton (); protected Singleton () {system. Out. println ("Singleton is create ");}
Private object readresolve () {// here, it is fixed to prevent the generation of new instances from always returning the current object return instance ;}
}

 



 
 

Implementation methods of Singleton Mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.