Ii. Singleton pattern)

Source: Internet
Author: User
I. Singleton mode definition

The Singleton mode is an object creation mode. classes with the following features become Singleton classes.

1. This class only has one unique instance.

2. The unique instance is self-instantiated.

3. This class provides this instance to the entire system.


It should be said that the singleton mode is the simplest of many design patterns, and it only involves the class itself. However, its ideas and functions are powerful. In actual development, where will the singleton mode be used?

For example, we generally only need one thread pool to manage threads. here we can use a singleton. Another example is the database connection in JDBC, because opening a connection consumes a lot of resources, you can also use a singleton here.


Ii. Advantages and applicable scenarios of the singleton Mode

Advantages:

1. There is only one object in the memory, saving the memory space.

2. Avoid frequent object creation and destruction to improve performance.

3. Avoid multiple usage of shared resources.

4. Global access.


Applicable scenarios:Because of the advantages of the singleton mode, it is a design mode that is used in programming. Common application scenarios:

1. objects that need to be frequently instantiated and then destroyed.

2. objects that consume too much time or too much resources, but are frequently used.

3. stateful tool objects.

4. objects that frequently access databases or files.

5. All other scenarios that require only one object that I have never used.


Iii. implementation methods and precautions of Singleton Mode
1. First, let's look at the Classic Singleton implementation method, also known as the lazy Singleton.

public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance(){if(singleton==null)singleton=new Singleton();return singleton;}}

In this case, the constructor is privatized to avoid class instantiation outside the class (reflection is not discussed for the moment), and then a public static method is used, instantiate a unique instance and provide it to the entire system.

Because only when we need to use a class change instance will we call the static method getinstance () to instantiate this unique instance, instead of instantiating this unique instance when the class is loaded, it is called a lazy Singleton.


The implementation is very concise, but it is indeed flawed. In the case of multiple threads, you may generate multiple instances, not the one you expect: the only one. That is, the above method is actually not thread-safe.

Assume that in thread 1, you need to use Singleton's instance. You call the getinstance () method because the getinstance () method has not been called anywhere before, therefore, if (Singleton = NULL) is true, it is necessary to enter the if code block and instantiate it. At this time, the singleton instance also needs to be used in thread 2, because thread 1 only enters the if code block and has not yet been instantiated, so in thread 2, if (Singleton = NULL) is still true and enters the if code block. The problem arises. Due to the multi-thread concurrency problem, two instances of different Singleton classes are obtained. It violates the original intention of the singleton design model.


There are many ways to solve the thread security in the Singleton, which are described in detail below.


2. Rewrite the lazy Singleton mode-add thread synchronization directly

public class Singleton {private static Singleton singleton;private Singleton() {}public static synchronized Singleton getInstance(){if(singleton==null){singleton=new Singleton();}return singleton;}}

Add the synchronized keyword directly to the getinstance () method to change it to a synchronous method, so the thread security problem is easily solved. This can greatly reduce the efficiency. This is because the thread synchronization consumes a lot of resources. Therefore, this method is not recommended.

3. Modify the lazy Singleton mode-double check and lock
public class Singleton {private static volatile Singleton singleton;private Singleton() {}public static Singleton getInstance(){if(singleton==null){synchronized (Singleton.class) {if(singleton==null)singleton=new Singleton();}}return singleton;}}

If there are 2nd direct synchronization methods, the getinstance () method will be synchronized every time it is called, greatly reducing the efficiency. Use the double check lock. Only when Singleton is null will it enter the synchronized code block.

Note: The volatile keyword must be added to the singleton statement. This volatile keyword is missing when many people use the double check lock. This is incorrect. For more information about the usage of this volatile, see the following article: http://blog.csdn.net/lonelyroamer/article/details/8133572.
Listing 3. Using the volatile variable for one-time secure Publishing

Note: In jdk1.4 and earlier versions, many JVM implementations of the volatile keyword will lead to the failure of the double check lock. Therefore, it can only be used after jdk1.5.

4. rewriting of the lazy Singleton model-the ELE. Me Singleton

public class Singleton {private static final Singleton singleton=new Singleton();private Singleton() {}public static  Singleton getInstance(){return singleton;}}

Singleton is instantiated directly when the class is loaded, so that there is only one unique instance, so there is no thread security problem mentioned above.

4. Create a singleton instance using a static private internal class

Public class Singleton {// static internal private class Private Static class singletonholder {static final Singleton uniqueinstance = new Singleton ();} private Singleton () {} public static Singleton getinstance () {return singletonholder. uniqueinstance ;}}

Because the static private internal class singletonholder will not load with Singleton, it will only load when it is used. Therefore, it has the characteristics of late instantiation, and all variables are automatically synchronized during class loading initialization, that is, it is thread-safe.
This method is very clever. there is a delay in creating a lazy Singleton without its thread security problems. I personally think this method is very good in Java.

5. Inheritance structure of the Singleton-registration Singleton

Check the Code:

Package COM. tao. pattern; import Java. lang. reflect. constructor; import Java. lang. reflect. invocationtargetexception; import Java. util. hashmap; public class javatest {public static void main (string [] ARGs) {singletonchild. getinstance (). show () ;}} class Singleton {protected Singleton () {}private static final hashmap <string, Singleton> m_register = new hashmap <string, Singleton> (); public static Singleton getinsta NCE (class <? Extends Singleton> clazz) {If (clazz! = NULL) {If (! M_register.containskey (clazz. getname () {synchronized (singleton. Class) {If (! M_register.containskey (clazz. getname () {try {constructor <? Extends Singleton> constructor = clazz. getdeclaredconstructor (new class [] {}); constructor. setaccessible (true); Singleton = constructor. newinstance (); If (Singleton! = NULL) m_register.put (clazz. getname (), Singleton);} catch (nosuchmethodexception | securityexception e) {e. printstacktrace ();} catch (instantiationexception e) {e. printstacktrace ();} catch (illegalaccessexception e) {e. printstacktrace ();} catch (illegalargumentexception e) {e. printstacktrace ();} catch (invocationtargetexception e) {e. printstacktrace () ;}}} return m_register.get (clazz. getname () ;}else {return NULL ;}} class singletonchild extends Singleton {private singletonchild () {} public static singletonchild getinstance () {return (singletonchild) Singleton. getinstance (singletonchild. class);} public void show () {system. out. println ("I have registered ");}}

This method is rarely used. It is mainly used for the inheritance structure of the Singleton mode, so that sub-classes can implement Singleton. Generally, when you want to use this method, you still need to check whether there is a problem with your design.

Iv. Considerations for the singleton Mode

1. Will the garbage collection mechanism recycle Singleton?

Before Java, the garbage collector has a bug, which can be used as garbage removal when a single instance is not referenced globally. That is to say, if a singleton only references this Singleton class, the singleton will be cleared as garbage.

After Java, this bug has been fixed and a global reference is no longer needed to protect the Singleton. Therefore, after 1.2, the singleton will not be recycled. You need to be careful before 1.2.

There is an article dedicated to this problem: http://blog.csdn.net/zhengzhb/article/details/7331354

2. Principles of reflection failure Singleton

public class Test {public static void main(String[] args) throws NoSuchMethodException,SecurityException, InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException {Singleton regSingleton1 = Singleton.getInstance();Singleton regSingleton2 = Singleton.getInstance();Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor(new Class[] {});constructor.setAccessible(true);Singleton regSingleton3=constructor.newInstance(null);System.out.println(regSingleton1==regSingleton2);System.out.println(regSingleton1==regSingleton3);}}

The printed result is

True

False

Reflection produces a new instance.

3. Load different classloaders to obtain multiple instances

4. serialization will generate multiple instances

5. Use threadlocal to generate a singleton for each thread

For example, in javaweb, a session needs to be generated for each thread, and each session does not affect each other. Here, threadlocal can be used to generate a session for each thread.

public class Singleton {private  static ThreadLocal<Singleton> thread_local=new ThreadLocal<Singleton>();private Singleton() {}public static Singleton getInstance() {if(thread_local.get()==null){thread_local.set(new Singleton());}return thread_local.get();}}

Test:

public class Test {public static void main(String[] args) throws NoSuchMethodException,SecurityException, InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException {final Singleton singleton1=Singleton.getInstance();Singleton singleton2=Singleton.getInstance();System.out.println(singleton1==singleton2);new Thread(){public void run() {Singleton singleton=Singleton.getInstance();System.out.println(singleton==singleton1);};}.start();}}

The output is as follows:

True

False

Each thread obtains a copy of an instance, which is different from that of a singleton instance.

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.