Java Design Pattern Learning record-Singleton mode

Source: Internet
Author: User

Objective

has introduced and learned two creation patterns, today to learn about another very common creation mode, the singleton mode.

The singleton mode is also known as a single-piece mode (or monomer mode), and the primary function is to control the number of instances of a type as one, and only one.

The realization of singleton mode in single case mode

There are a number of ways to implement a singleton pattern, which can be broadly divided into the following two types.

External mode

Do some "try-use" work when using some global objects. That is, if the global object that you want to use does not exist, create one yourself, put it in the global position, or use it directly if you have one.

Internal Implementation method

The type itself controls the number of normal instances, regardless of whether the client has tried or not, and the type itself controls only one instance, and the client uses this out-of-the-box unique instance.

With the universal application of cluster and multi-core technology, it is more and more difficult to realize the real singleton through simple type internal control, and it is not realistic to try to achieve the "singleton" in distributed environment by the classic Singleton mode. So the current introduction of this single case is semantically limited.

Characteristics of the Singleton model

Although the singleton model also belongs to the creation model, freshwater it has its own unique characteristics.

    • The Singleton class has only one instance.
    • The Singleton class creates the instance itself, creating its own instance object inside the class.
    • Expose this instance interface to the entire system.

It is also important to note that singleton mode only cares about the creation of class instances and does not care about the specific business functions.

Range of singleton patterns

The current Java implementation of the Singleton is a classloader and its sub-classloader range. Because ClassLoader creates an instance of a class in a responsive manner when loading a singleton class implemented by the A Hungry man type. This also means that if there is more than one classloader in a virtual machine (though ClassLoader follows the parental delegation model, there will be no handler for the parent loader, and then the custom loader performs the class load scenario.) , and these classloader are loaded with a class, even if the class is a singleton, it will produce many instances. If there is more than one virtual machine on a machine, then there should be at least one instance of this class in each virtual machine, which means that there are many instances on the machine, not even a single case.

Again, it is emphasized that the singleton scope currently discussed does not apply to clustered environments.

Singleton pattern Type A hungry man single case

A hungry man singleton is when the class is loaded, the unique instance has been created.

An example of the following code:

/*** A hungry man single-case mode **/ Public classHungrysingleton {/*** Define a static variable to store the instance, created when the class is loaded, and created only once. */    Private StaticHungrysingleton Hungrysingleton =NewHungrysingleton (); /*** Privatization of construction methods, prohibit external creation of instances. */    PrivateHungrysingleton () {System.out.println ("Create Instance"); }    /*** Method of obtaining unique instances externally *@return     */     Public StaticHungrysingleton getinstance () {returnHungrysingleton; }}
Lazy Single-case

Lazy Singleton refers to a class that does not create a singleton object when it is loaded, and is created only when it is first used, and no instances of the class are created after the first time it is created.

An example of the following code:

/*** Lazy type single case*/ Public classLazysingleton {/*** Define a static variable to store the instance. */    Private StaticLazysingleton Lazysingleton =NULL; /*** Privatization of construction methods, prohibit external creation of instances. */    PrivateLazysingleton () {}/*** methods to obtain unique instances externally
* Initialize static variables when no initialization is found. * @return */ Public StaticLazysingleton getinstance () {if(NULL==Lazysingleton) {Lazysingleton=NewLazysingleton (); } returnLazysingleton; }}
Registration Single-CASE

A registered singleton actually maintains an instance of a set of singleton classes that exist in a register (for example, map), use an instance that has already been registered, return directly from the register, not registered, then register, and then return.

The following code example:

/*** Registration type Single case*/ Public classRegistersingleton {/*** Create a register to hold all Singleton objects*/    Private StaticMap<string,registersingleton> Registerbook =NewHashmap<>(); /*** Privatization of construction methods, prohibit external creation of instances*/    PrivateRegistersingleton () {}/*** Registered Instance *@paramname on the name register *@paramRegistersingleton An instance on the registration book*/     Public Static voidregisterinstance (String Name,registersingleton Registersingleton) {if(!Registerbook.containskey (name))        {registerbook.put (Name,registersingleton); }    }    /*** Gets instance, if called when not registered, will return NULL *@paramname on the name register *@return     */     Public StaticRegistersingleton getinstance (String name) {returnregisterbook.get (name); }}

Because the A hungry man-type Singleton creates an instance when the class is loaded, the instance is always the same and therefore thread-safe. But the lazy singleton is not thread-safe, and in a lazy singleton it is possible that two threads create two different instances, because the getinstance () method in the lazy singleton is not thread-safe. So if you want to make the lazy slip into thread-safe, you need to lock it in the getinstance () method.

As shown below:

   /**     * methods     for obtaining unique instances externally * Initialize static variables      * @ return * * When the discovery is not initialized      staticsynchronized  Lazysingleton getinstance () {        if(  Null= =Lazysingleton)            {new  Lazysingleton ()        ;        } return Lazysingleton;    }

However, this increase in resource consumption, the effect of delayed loading is achieved, but the use of resources is more expensive, so it is not recommended. Both thread-safe and lazy loading are guaranteed. Based on this problem there is another way of singleton mode, static internal class singleton .

Static inner-class single case

Static internal class single-case a hungry man and lazy-type combination.

The following code example:

/*** Internal static class type single case*/ Public classStaticclasssingleton {/*** Privatization of construction methods, prohibit external creation of instances. */    PrivateStaticclasssingleton () {System.out.println ("Create an instance"); }    /*** private static inner class, can only be called by internal. */    Private Static classsingleclass{Private StaticStaticclasssingleton Singleton =NewStaticclasssingleton (); }    /*** Method of obtaining unique instances externally *@return     */     Public StaticStaticclasssingleton getinstance () {returnSingleclass.singleton; }}
Double check and lock type single case

The method of static inner class is implemented by combining a hungry man and lazy, that is, delayed loading and thread safety. The following is another example of how lazy loading can be implemented in a way that ensures thread safety.

The following code example:

/*** Double check and lock type single case*/ Public classDoublechecklocksingleton {/*** Static variables, used to store instances. */    Private volatile StaticDoublechecklocksingleton Doublechecklocksingleton =NULL; /*** Privatization of construction methods, prohibit external creation of instances. */    PrivateDoublechecklocksingleton () {}/*** Double check lock mode to ensure thread safety and get unique instance *@return     */     Public StaticDoublechecklocksingleton getinstance () {//first check if the instance already exists, does not exist, enters the code block        if(NULL==Doublechecklocksingleton) {            synchronized(Doublechecklocksingleton.class){                //since synchronized is also a re-entry lock, it is possible for a thread to enter this synchronization block multiple times If an instance has been created the first time it is entered, then the second entry is not created.                 if(NULL==Doublechecklocksingleton) {Doublechecklocksingleton=NewDoublechecklocksingleton (); }            }        }        returnDoublechecklocksingleton; }}

As shown above, the so-called "double check lock" mechanism, not every time into the getinstance () method need to lock, but when entering the method, first check whether the instance already exists, if it does not exist before the following synchronization block, this is the first check, after entering the synchronization block, again check whether the instance already exists, If it does not exist, create an instance in the synchronization block, which is the second check. This is a process that only needs to be synchronized once.

It is also important to note that when using "double check lock", you need to use the keyword volatile on the variable, which is the role of the volatile modifier of the value of the variable is not cached by the local thread, all read and write to the variable is directly operating shared memory, This ensures that multiple threads can handle the variable correctly . May not understand the Java memory mode of the friend is not very good to understand the meaning of this sentence, you can go to see (JVM Learning record-java memory model (a), the JVM learning record-java memory model (ii)) to understand the Java memory model, let me briefly explain, Volatile is a keyword that guarantees that the variables that are manipulated by each thread are seen by other threads, which means that if the first thread has created an instance, it only puts it in its own thread and the other threads are invisible. This time if the other thread again to determine whether the instance is already in existence, it is found that there is no instance will be created another instance, and then placed in their own thread, if so, we write the singleton mode is meaningless. The issue of support for volatile in previous versions of JDK1.5 may cause "double check lock" to fail, so if you want to use the double check lock type Singleton, you can only use versions above JDK1.5.

Enumeration single-Case

The introduction of a new feature in JDK1.5, enumerations, and enumerations to implement a singleton, is now the best way to do it. Java's enumeration types are essentially full-featured classes, so you can have your own properties and methods.

Or you can use code examples to explain it.

The following code example:

/** *Single- element enumeration for single-instance mode*/ Public enumEnumsingleton {/*** Must be a cell, because an element is an instance. */INSTANCE; /*** Test Method 1 *@return     */     Public voiddosomething () {System.out.println ("# # # #测试方法 ######"); }    /*** Test Method 2 *@return     */     PublicString getsomething () {return"Got some content."; }}

In the example above, enumsingleton.instance can obtain the desired instance, and the method of invoking the singleton can be EnumSingleotn.INSTANCE.doSomeThing ().

Here's a look at how the enumeration guarantees the singleton:

The construction method of the first enumeration is explicitly private, the constructor is executed when the enumeration instance is used, and each enumeration instance is a static final type, indicating that the enumeration instance can only be assigned one time, so that the instance is created when the class is initialized, which also illustrates the enumeration singleton, In fact, it is a a hungry man single-case approach. This way, the simplest code guarantees both thread safety and the simplicity of the code.

It is also worth noting that the singleton implementation of the enumeration guarantees a single case security after serialization. In addition to an enumerated singleton, a singleton in other ways can create multiple instances by reflection or deserialization.

So the best way to use a singleton is to use enumerations. It's both simple and safe.

Java design Pattern Learning record-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.