Create a singleton pattern (Java edition)

Source: Internet
Author: User
Tags volatile

1. Introduction to the Singleton mode

The singleton pattern is one of the most widely used patterns, and it may be the only design pattern that many junior engineers can use. When you apply this pattern, the class of the Singleton object must guarantee that only one instance exists. Many times the entire system only needs to have a global object, which helps us coordinate the overall behavior of the system. As in an application, there should be only one imageloader instance, and this imageloader contains thread pool, cache system, network request, etc., so it consumes resources, so there is no reason to let it construct multiple instances. The case that the object is not freely constructed is the use scenario of a singleton pattern.

2. Definition of a singleton pattern

Make sure that there is only one instance of a class, and instantiate it yourself and provide this instance to the entire system.

3. Usage scenarios for single-instance mode

Make sure that a class has and only one object of the scene, to avoid producing multiple objects that consume too much resources, or that some type of object should only have and only one. For example, to create an object that consumes too much resources, such as accessing resources such as IO and databases, you should consider using singleton mode.

4. UML class diagram of single case mode

Figure 4-1 UML class diagram of a single case pattern

Role Description:

(1) client--high-level client;

(2) singleton--single case class.

The implementation of the singleton mode is mainly the following key points:

(1) The construction function is not open to the outside, generally private;

(2) Returning a singleton class object through a static method or enumeration;

(3) Ensure that the object of the Singleton class has only one, especially in the multi-threaded environment ;

(4) Ensure that the object is not rebuilt when the Singleton class object is deserialized.

By privatizing the constructor of a singleton class, the client code cannot manually construct an object of the Singleton class by using new. The Singleton class exposes a public static method that the client needs to call this static method to obtain the unique object of the Singleton class, 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 multi-threaded environment is also only one, which is a difficult place in the singleton pattern implementation.

5. How to implement the singleton mode

1. A Hungry man mode

public class Singleton{private Static Singleton instance = new Singleton ();p rivate Singleton () {}public static Singleton g Etinstance () {return instance;}}

2. Lazy mode

The lazy pattern is to declare a static object and initialize it when the user first calls getinstance, while the A hungry man pattern is initialized when the static object is declared.

public class Singleton{private Static Singleton instance = Null;private Singleton () {}public static synchronized Singleton GetInstance () {if (instance = = null) {instance = new Singleton ();} return instance;}}

The getinstance () method adds the Synchronized keyword, that is, getinstance is a synchronous method, which is what is described above as a means of guaranteeing the uniqueness of singleton objects in multithreaded situations. Think about it, you may find a problem, even if the instance has been initialized (the first call will be initialized instance), each call to GetInstance method will be synchronized, which will consume unnecessary resources, which is also the biggest problem of lazy singleton mode.

Finally, the advantage of the lazy singleton model is that the singleton is instantiated only when it is used, saving resources to a certain extent; The disadvantage is that the first time the load needs to be instantiated in a timely manner, the response is slightly slow, the biggest problem is each call getinstance synchronization, resulting in unnecessary synchronization overhead. This mode is generally not recommended for use.

3, double Checklock (DCL) to achieve a single case

The advantage of the DCL mode is that both the singleton and the thread safety can be initialized when needed, and the getinstance is not synchronized when the singleton object is initialized.

public class Singleton{private Static Singleton instance = Null;private Singleton () {}public static Singleton getinstance ( {if (instance = = null) {synchronized (Singleton.class) {if (instance = = null) {instance = new Singleton ();}}} return instance;}}

The highlights of this program are naturally in the GetInstance method, you can see the GetInstance method in the instance two times to be sentenced to empty: the first layer of judgment is mainly to avoid unnecessary synchronization, the second layer of judgment is to create an instance in the case of NULL. What does that mean? is not a little touch the brain, the following together to analyze.

Assuming that thread a executes to the instance= new Singleton () statement, it looks like a code, but in fact it is not an atomic operation, and this code will eventually be compiled into multiple assembly instructions, which roughly does 3 things:

(1) Allocating memory to the instance of Singleton;

(2) Call the constructor of Singleton () to initialize the Member field;

(3) Point the instance object to the allocated memory space (instance is not NULL at this time).

However, because the Java compiler allows the processor to execute in a disorderly order, and the JMM (Javamemory model, the Java memory model) in the cache, register to main memory writeback order, the second and third Order of the above is not guaranteed. In other words, the order of execution may be either 1-3-2 or either. If the latter, and before the execution of 3, 2 is not executed, was switched to thread B, this time instance because already in thread A has been executed in the 3rd, instance is already non-empty, so, Thread B takes the instance directly, and then it goes wrong when it is used, which is the DCL failure problem, and it is likely to hide for a long time that the hard-to-follow error is difficult to reproduce.

After JDK1.5, sun officials have noticed this issue, adjusted the JMM, materialized the volatile keyword, so if the JDK is a 1.5 or later version, you only need to change the definition of instance to private volatile static Singleton instance = NULL to ensure that the instance object is read from main memory each time, you can use the DCL notation to complete the singleton mode. Of course, volatile can affect performance more or less, but it is worthwhile to sacrifice this performance, given the correctness of the program.

The advantages of DCL: The high utilization of resources, the first time the execution of GetInstance Singleton object will be instantiated, high efficiency. Cons: The first load reaction is slightly slower, and the Java memory model occasionally fails because of the reason. In the high Concurrency environment also has certain flaw, although the occurrence probability is very small. The DCL pattern is the most used single-instance implementation, which can instantiate singleton objects when needed, and is able to guarantee uniqueness of singleton objects in most scenarios, unless your code is more complex or less than the JDK1.5 version of the concurrency scenario, which generally satisfies the requirements.

4. Static internal class

Although the DCL solves some problems such as resource consumption, redundant synchronization, and line Cheng, it still fails in some cases. This problem is called double check lock invalidation. It is recommended to replace it with a static inner class.

public class Singleton{private Singleton () {}public static  Singleton getinstance () {return Singletonholder.instance;} private static class Singletonholder{private static final Singleton instance = new Singleton ();}}

When the Singleon class is loaded for the first time, the instance is not initialized, which causes instance to be initialized only if the GetInstance method of Singleton is called the first time. Therefore, the first call to the GetInstance method causes the virtual machine to load the Singletonholder class, not only to ensure thread safety, but also to ensure the uniqueness of singleton objects, as well as to delay the instantiation of Singleton, so this is the recommended singleton mode implementation.

5. Enumeration

public enum singletonenum{instance;public void DoSomething () {System.out.println ("do sth.");}

The simplest way to do this is to enumerate the greatest advantages of a single example, in Java, as with ordinary classes, there are not only fields, but also their own methods. Most importantly, the creation of the default enumeration instance is thread-safe, and in any case it is a singleton.

Serialization allows you to write a singleton instance object to disk and then read it back, effectively obtaining an instance. Even if the constructor is private, deserialization can still create a new instance of the class in a special way, equivalent to calling the constructor of the class. The deserialization operation provides a very special hook function, which has a private, instantiated method, Readresolve (), which allows the developer to control the deserialization of the object. For example, if you want to eliminate the need to regenerate objects when the singleton object is deserialized in several examples, you must add the following method:

Private Object Readresolve () throws Objectstreamexception{return instance;}

That is, the instance object is returned in the Readresolve method instead of the default regeneration of a new object. For enumerations, this problem does not exist, because even deserializing it does not regenerate new instances.

6. Use the container

public class Singletonmanager{private static map<string,object> Objmap = new hashmap<string,object> (); Private Singletonmanager () {}public static void Registerservice (String key,object instance) {if (!objmap.containskey ( Key) {Objmap.put (key, instance);}} public static Object GetService (String key) {return objmap.get (key);}}

At the beginning of the program, a number of singleton types are injected into a unified management class, and objects of the object's corresponding type are obtained according to key when used. This way allows us to manage multiple types of singleton, and in use can be achieved through a unified interface to obtain operations, reduce the user's cost of use, but also to hide the specific implementation of the user, reducing the coupling degree.

Create a singleton pattern (Java edition)

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.