5 ways to implement a single instance of Java

Source: Internet
Author: User
Tags serialization

1. What is a singleton mode

A singleton pattern refers to the existence of only one instance of an application throughout its life cycle. Singleton mode is a widely used design pattern. He has a number of advantages to avoid duplicate creation of instance objects, reduce the overhead of creating instances, and save memory.

2. The difference between a singleton and a static class

First understand what is static class, Static class is a class is a static method and static field, the constructor is private decoration, and therefore cannot be instantiated. The math class is a static class.

Once you know what a static class is, here's a look at the difference between them:

1) First the singleton mode will provide you with a globally unique object, static classes just provide you with a lot of static methods, these methods do not create objects, through the class can be directly called;

2) The flexibility of the singleton mode is higher, the method can be override, because static classes are static methods, so can not be override;

3) If it is a very heavy object, the singleton mode can be lazy loading, static class will not be able to do;

When should you use a static class, and when should I use a singleton mode? First, if you just want to use some tool methods, it is better to use static class, static analogy singleton class faster, because the static binding is done at compile time. If you want to maintain state information, or access resources, you should use singleton mode. It can also be said that when you need to object-oriented capabilities (such as inheritance, polymorphism), choose the Singleton class, when you just provide some methods to choose static Class.

3. How to implement a singleton mode

1. A Hungry man mode

The so-called a hungry man mode is immediately loaded, the general situation before calling the Getinstancef method has already produced an instance, that is, when the class load has been generated. The disadvantage of this model is obvious, is to occupy resources, when the Singleton class is very large, in fact, we want to use the time to generate instances. Therefore, this approach is suitable for classes that use less resources and are used at initialization time.

class SingletonHungary {    privatestaticnewSingletonHungary();    //将构造器设置为private禁止通过new进行实例化    privateSingletonHungary() {            }    publicstaticgetInstance() {        return singletonHungary;    }}

2. Lazy mode

Lazy mode is delayed loading, also known as lazy loading. Create instances when the program needs to be used, thus ensuring that the memory is not wasted. For the lazy mode, here are 5 ways to implement, some implementations are thread insecure, that is, in the context of multi-threaded concurrency may occur resource synchronization problems.

First way, in a single-threaded no problem, in the multi-threaded problem.

//Singleton mode of lazy implementation of thread insecurityclassSingletonLazy1 {Private StaticSingletonLazy1 Singletonlazy;Private SingletonLazy1() {    } Public StaticSingletonLazy1getinstance() {if(NULL= = Singletonlazy) {Try{//Simulate doing some preparatory work before creating the objectThread.Sleep( +); }Catch(Interruptedexception e) {e.Printstacktrace(); } Singletonlazy =New SingletonLazy1(); }returnSingletonlazy; }}

We simulate 10 asynchronous threads to test:

 Public classsingletonlazytest { Public Static void Main(string[] args) {thread2[] Threadarr =Newthread2[Ten]; for(inti =0; I < Threadarr.length; i++) {Threadarr[i] =New Thread2(); Threadarr[i].Start(); }    }}//Test threadclassThread2extendsThread {@Override     Public void Run() {System. out.println(SingletonLazy1.getinstance().hashcode()); }}

Operation Result:

1241912391241912398720964661603289047169803234219136676183717393641241912391723650563367137303

Can see their hashcode is not all the same, in the multi-threaded environment, produced a number of objects, do not meet the requirements of the singleton mode.

So how to make thread safe? In the second method, we use the Synchronized keyword to synchronize the getinstance method.

//Singleton pattern of lazy implementation 2--thread safety//By setting the synchronization method, the efficiency is too low, the whole method is lockingclassSingletonLazy2 {Private StaticSingletonLazy2 Singletonlazy;Private SingletonLazy2() {    } Public Static synchronizedSingletonLazy2getinstance() {Try{if(NULL= = Singletonlazy) {//Simulate doing some preparatory work before creating the objectThread.Sleep( +); Singletonlazy =New SingletonLazy2(); }        }Catch(Interruptedexception e) {e.Printstacktrace(); }returnSingletonlazy; }}

Using the test class above, test the result:

1210004989121000498912100049891210004989121000498912100049891210004989121000498912100049891210004989

As you can see, this approach achieves thread safety. But the disadvantage is that the efficiency is too low, is running synchronously, the next thread wants to get the object, it must wait for the last thread to release, can continue to execute.

Then we can not lock the method, but the code inside the lock, but also to achieve thread safety. However, this approach is synchronous and inefficient, as is the case with synchronous methods.

//Singleton pattern of lazy implementation 3--thread safety//By setting the synchronization code block, the efficiency is too low, the entire code block is lockingclassSingletonLazy3 {Private StaticSingletonLazy3 Singletonlazy;Private SingletonLazy3() {    } Public StaticSingletonLazy3getinstance() {Try{synchronized(SingletonLazy3.class) {if(NULL= = Singletonlazy) {//Simulate doing some preparatory work before creating the objectThread.Sleep( +); Singletonlazy =New SingletonLazy3(); }            }        }Catch(Interruptedexception e) {//Todo:handle exception}returnSingletonlazy; }}

Let's continue to optimize the code, we just lock the code that creates the object, but does this guarantee thread safety?

//Singleton pattern of lazy implementation 4--thread insecure//By setting the synchronization code block, only the code that creates the instance is synchronized//But still a thread-safe issueclassSingletonLazy4 {Private StaticSingletonLazy4 Singletonlazy;Private SingletonLazy4() {    } Public StaticSingletonLazy4getinstance() {Try{if(NULL= = Singletonlazy) {//code 1                //Simulate doing some preparatory work before creating the objectThread.Sleep( +);synchronized(SingletonLazy4.class) {Singletonlazy =New SingletonLazy4();//Code 2}            }        }Catch(Interruptedexception e) {//Todo:handle exception}returnSingletonlazy; }}

Let's look at the results of the operation:

12100049891425839054172365056338900126613569140483890012661560241484278778395124191239367137303

As a result, this approach does not guarantee thread safety, why? We assume that there are two threads A and b go to ' Code 1 ' at the same time, because the object is still empty, so all can go inside the method, thread a first grab the lock, create the object. When the lock is released, thread B gets the lock and goes to ' Code 2 ' and creates an object, so there is no guarantee for a single case in a multithreaded environment.

Let's continue to optimize, since there are problems with the above method, then we in the synchronization code block once again to do a null judgment is not OK, this way is our DCL double check lock mechanism.

//Singleton pattern of lazy implementation 5--thread safety//By setting the synchronization code block, using the DCL double check lock mechanism//Use double check lock mechanism to successfully solve the problem of thread insecurity and efficiency in the singleton mode of lazy implementation//DCL is also the solution for most multithreaded combined with a singleton patternclassSingletonLazy5 {Private StaticSingletonLazy5 Singletonlazy;Private SingletonLazy5() {    } Public StaticSingletonLazy5getinstance() {Try{if(NULL= = Singletonlazy) {//Simulate doing some preparatory work before creating the objectThread.Sleep( +);synchronized(SingletonLazy5.class) {if(NULL= = Singletonlazy) {Singletonlazy =New SingletonLazy5(); }                }            }        }Catch(Interruptedexception e) {//Todo:handle exception}returnSingletonlazy; }}

Operation Result:

124191239124191239124191239124191239124191239124191239124191239124191239124191239124191239

We can see that the DCL double check lock mechanism is a good solution to the lazy load singleton mode efficiency problems and thread safety issues. That's the way we're most used to.

3. Static Inner class

We can also use a static inner class to implement a singleton pattern with the following code:

//using static internal classes to implement singleton mode-thread safetyclassSingletonstaticinner {Private Singletonstaticinner() {            }Private Static classSingletoninner {Private StaticSingletonstaticinner Singletonstaticinner =New Singletonstaticinner(); } Public StaticSingletonstaticinnergetinstance() {Try{Thread.Sleep( +); }Catch(Interruptedexception e) {//TODO auto-generated catch blockE.Printstacktrace(); }returnSingletoninner.Singletonstaticinner; }}

As you can see in this way we do not explicitly do any synchronous operation, so how does he ensure thread safety? Like the A Hungry man model, the JVM guarantees that static members of a class can only be loaded once, so that only one instance object is guaranteed from the JVM level. So what's the difference between this and the A Hungry man model? Does it also load immediately? Otherwise, when a class is loaded, its inner class is not loaded at the same time. A class is loaded when and only if one of its static members (static domain, constructor, static method, and so on) is called.

It can be said that this method is the optimal solution to the single-case pattern.

4. Static code block

This provides a static code block implementation of the singleton pattern. This approach is similar to the first one and is also a a hungry man pattern.

//使用静态代码块实现单例模式class SingletonStaticBlock {    privatestatic SingletonStaticBlock singletonStaticBlock;    static {        newSingletonStaticBlock();    }    publicstaticgetInstance() {        return singletonStaticBlock;    }}

5. Serialization and deserialization

Why should LZ mention serialization and deserialization? Because singleton mode guarantees thread safety, there are situations in which multiple objects can be generated in the case of serialization and deserialization. Run the following test class,

 Public classsingletonstaticinnerserializetest { Public Static void Main(string[] args) {Try{Singletonstaticinnerserialize serialize = singletonstaticinnerserialize.getinstance(); System. out.println(Serialize.hashcode());//SerializationFileOutputStream fo =NewFileOutputStream ("tem"); ObjectOutputStream oo =NewObjectOutputStream (FO); Oo.writeobject(serialize); Oo.Close(); Fo.Close();//DeserializationFileInputStream fi =NewFileInputStream ("tem"); ObjectInputStream Oi =NewObjectInputStream (FI); Singletonstaticinnerserialize serialize2 = (singletonstaticinnerserialize) oi.ReadObject(); Oi.Close(); Fi.Close(); System. out.println(Serialize2.hashcode()); }Catch(Exception e) {e.Printstacktrace(); }    }}//Using anonymous inner classes to implement singleton patterns, in scenarios where serialization and deserialization are encountered, the same instance is not obtained//solve this problem by using the Readresolve method when serializing, i.e. removing the part of the commentclassSingletonstaticinnerserializeImplementsSerializable {/*** March 28, 2018     */    Private Static Final LongSerialversionuid = 1L;Private Static classInnerclass {Private StaticSingletonstaticinnerserialize singletonstaticinnerserialize =New singletonstaticinnerserialize(); } Public StaticSingletonstaticinnerserializegetinstance() {returnInnerclass.singletonstaticinnerserialize; }//protected Object Readresolve () {//System.out.println ("Call the Readresolve method");//return innerclass.singletonstaticinnerserialize;//  }}

can see:

8651139381078694789

The result shows that there are two different object instances, which violates the singleton pattern, so how to solve this problem? The workaround is to use the Readresolve () method in deserialization to remove the above comment code and run it again:

865113938调用了readResolve方法865113938

The question is, where the Readresolve () method is sacred, in fact, when the JVM "assembles" a new object from memory, it automatically calls the Readresolve method to return the object that we specified, and the singleton rule is guaranteed. The advent of the Readresolve () allows the programmer to control the objects that are obtained by deserializing themselves.

5 ways to implement a single instance of Java

Related Article

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.