Why enumeration class to implement Singleton pattern more and more popular?

Foreword

Singleton Design Pattern in Java is the simplest one, only one class will be able to implement singleton pattern, but you can not underestimate the Singleton pattern, though it came from a relatively simple design, but you achieve them You will encounter a lot of pits, so fasten your seat belts, on the train.

Singleton pattern defined

Singleton is in the program run only instantiated once, to create a globally unique object, a bit like Java's static variables, but Singleton pattern due to static variables, static variables will be created when the program starts, it will cause a lot of waste of resources, good singleton will not have this problem. Many of the tools developed are applied Singleton pattern, thread pool, cache, logs and other objects, they only need to create an object, if you create multiple instances, may lead to unpredictable problems, such as waste of resources, The results address the inconsistencies and other issues.

Examples of realization of ideas single

  • Examples of static objects
  • Privatization of the constructor, create an instance via the constructor ban
  • Provides a public static method, returns the unique instance for

The benefits of a single case

  • Only one object, less memory cost, good performance (generated when an object requires more resources, such as reading configuration, dependency produce other objects, it may be produced directly from a singleton object when the application starts, let memory forever the way to solve)

  • Avoid multiple assignment of resources (a write file operation, there is only one instance in memory, to avoid the same resource at the same time file write operations
    )

  • In the system set global access point, and to optimize access to shared resources (such as: the design of a single-class embodiment, the mapping is responsible for handling all data tables)

Examples of single-mode

Mainstream writing singleton pattern are starving, lazy mode, double-check the lock mode, static inner classes Singleton, Singleton mode enumeration class implements five ways in which lazy mode, double-check the wording of the two modes improper lock mode will result in a multithreaded singleton or not a single case of abnormal, we will be back to tell you in detail. We started our way of writing a single case of a hungry man from the most basic model.

Starving mode

Starving model used is a simple and crude forms, in the definition of static property, directly instantiated object. code show as below:

//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
public class SingletonObject1 {
    // 利用静态变量来存储唯一实例
    private static final SingletonObject1 instance = new SingletonObject1();

    // 私有化构造函数
    private SingletonObject1(){
        // 里面可能有很多操作
    }

    // 提供公开获取实例接口
    public static SingletonObject1 getInstance(){
        return instance;
    }
}

Advantages and disadvantages of starving mode

advantage
  • JVM thread safe level, static keyword to ensure that when referencing this variable, this variable so on write operations are completed
Shortcoming
  • Lazy loading can not be achieved, resulting in a waste of space, if a larger analogy, when we initialized to load this class, but we did not use this class for a long time, which leads to a waste of memory space.

Lazy mode

Like a lazy lazy mode when hungry will only try to find something to fill his stomach, never before ready food to prevent hungry. Lazy mode implements lazy loading, to solve the problem of wasted space caused by starving mode to achieve when using to initialize the class, but also introduces other problems, let's take a look at this lazy mode

public class SingletonObject2 {
    // 定义静态变量时,未初始化实例
    private static SingletonObject2 instance;

    // 私有化构造函数
    private SingletonObject2(){

    }

    public static SingletonObject2 getInstance(){
        // 使用时,先判断实例是否为空,如果实例为空,则实例化对象
        if (instance == null)
            instance = new SingletonObject2();
        return instance;
    }
}

Above this lazy mode implementation code, in the case of multi-threaded and can not be guaranteed to be a singleton, the main problems occur when an object is instantiated, so I alone to instantiate the proposed code, for everyone to talk about why more than there may be a case where the thread will initialize multiple instances.

     1   if (instance == null)
     2       instance = new SingletonObject2();

Suppose there are two threads into the 1 position, because we do not have any resources protection measures, so two threads judgments instanceare empty, are examples of code to execute 2, so the situation there will be multiple instances.

We already know that the above code appears multiple instances because there is no protection of resources, if we lock the resource, is not able to solve the problem of multiple instances? Indeed, we give getInstance()methods add synchronizedkeywords that getInstance()method became a protected resource will be able to solve the problem of multiple instances. Plus synchronizedafter key codes are as follows:

public class SingletonObject3 {
    private static SingletonObject3 instance;

    private SingletonObject3(){

    }

    public synchronized static SingletonObject3 getInstance(){
        /**
         * 添加class类锁,影响了性能,加锁之后将代码进行了串行化,
         * 我们的代码块绝大部分是读操作,在读操作的情况下,代码线程是安全的
         *
         */

        if (instance == null)
            instance = new SingletonObject3();
        return instance;
    }
}

This really solve the situation may occur multiple instances, but added synchronizedafter the keywords, the introduction of a new problem, after locking the code serialization, reducing the performance of the system. getInstance()Most methods of operations are read operations, the read operation is thread-safe.

Advantages and disadvantages of lazy mode

advantage
  • It implements lazy loading, saving memory space
Shortcoming
  • In the case of an unlocked, thread-safe, multiple instances may arise
  • In the case of locked, the program will be serialized, so that there are serious system performance issues

Double-check lock mode

In lazy mode we know that getInstance()most of the methods of operation are read, the read operation is thread-safe, for getInstance()a method to lock caused a lot of performance problems, thereby creating a more elegant way of locking both able to getInstance()lock, but without sacrificing performance, this model is what we now know to double-check the lock mode , we take a look at a single case to achieve double-check lock modes:

public class SingletonObject4 {
    private static SingletonObject4 instance;

    private SingletonObject4(){

    }

    public static SingletonObject4 getInstance(){

        // 第一次判断,如果这里为空,不进入抢锁阶段,直接返回实例
        if (instance == null)
            synchronized (SingletonObject4.class){
                // 抢到锁之后再次判断是否为空
                if (instance == null){
                    instance = new SingletonObject4();
                }
            }

        return instance;
    }
}

Double check the lock mode can be said is a very good example to achieve single-mode, single cases solved, performance, thread safety issues, to achieve the above looks perfect, but the realization of the code above, in the case of multi-threaded, may there will be a null pointer problem , let's work together to understand why there is a null pointer problem.

The problem is due to a null pointer virtual machine optimization and instruction reordering caused when we instantiate the object inside the virtual opportunity to optimize the code, maybe you do not understand, we look at the following piece of code

    private SingletonObject4(){
     1   int x = 10;
     2   int y = 30;
     3  Object o = new Object();
                
    }

JVM is instantiated SingletonObject4()not necessarily in the order of 1, 2 executes, it will be optimized JVM, may be 3,1,2, it may be 2,3,1, JVM will ensure that eventually instantiated completed. If the constructor operation is relatively long, in order to improve efficiency, the JVM will return object is instantiated completed constructor function attributes. This also resulted in other threads to obtain instance, in the use of a property, the property may not be instantiated completed, it will cause a null pointer exception.

To solve the problem caused null pointer exception of the above double-check lock mode, you need to use volatilekeywords, volatilekeyword strictly follow the happens-beforeprinciple that before a read operation, write operation must be completed. Add volatilesingleton pattern code following keywords:

    // 添加volatile关键字
    private static volatile SingletonObject5 instance;

    private SingletonObject5(){

    }

    public static SingletonObject5 getInstance(){

        if (instance == null)
            synchronized (SingletonObject5.class){
                if (instance == null){
                    instance = new SingletonObject5();
                }
            }

        return instance;
    }
}

Add volatiledouble check the lock mode after keywords are a good example to achieve single-mode, to ensure the security thread in the case of multi-threaded performance there will not be a problem.

Internal static type Singleton

Internal static type single embodiment mode is also called single-mode embodiment the holder, the inner class instance is created, because the loading of an external JVM class, is not loaded static inner classes, only internal class property / method is invoked It will be loaded and initialized static properties. Static properties of staticmodified to ensure only be instantiated once, and strictly ensure the instantiation order. Internal static type singleton pattern code is as follows:

public class SingletonObject6 {


    private SingletonObject6(){

    }
    // 单例持有者
    private static class InstanceHolder{
        private  final static SingletonObject6 instance = new SingletonObject6();

    }
    
    // 
    public static SingletonObject6 getInstance(){
        // 调用内部类属性
        return InstanceHolder.instance;
    }
}

Internal static type singleton pattern is a good single embodiment mode of realization, is commonly used to achieve a single-mode embodiment. In the absence of any added locks to ensure the safety of multi-threaded, and did not waste any performance impact and space.

Example single-mode enumeration class

Enum class implements the singleton pattern is effective java authors strongly recommended mode to achieve a single case, enumerated type is thread-safe, and only loaded once, designers full use of this feature to achieve Singleton pattern, enumeration very simple wording, enumerated type and single mode embodiment implemented in a single embodiment with the only achieve not damaged.

public class SingletonObject7 {


    private SingletonObject7(){

    }

    /**
     * 枚举类型是线程安全的,并且只会装载一次
     */
    private enum Singleton{
        INSTANCE;

        private final SingletonObject7 instance;

        Singleton(){
            instance = new SingletonObject7();
        }

        private SingletonObject7 getInstance(){
            return instance;
        }
    }

    public static SingletonObject7 getInstance(){

        return Singleton.INSTANCE.getInstance();
    }
}

A method for destroying singletons and solutions

1, in addition to enumerating, other methods are destroyed by way of a single reflector, the reflective generated new object by calling the constructor, so if we want to prevent destruction of a single embodiment, may be determined in the constructor, Ruoyi there are instances, prevent the formation of the new instance, the solution is as follows:

private SingletonObject1(){
    if (instance !=null){
        throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
    }
}

2, if the singleton class implements the Serializable serial interfaces, can be destroyed by deserializing a single embodiment, so we can not implement the serialization interface if the interface have to implement the serialization, deserialization can be rewritten readResolve method (), returned directly related singleton object deserialization.

  public Object readResolve() throws ObjectStreamException {
        return instance;
    }

At last

Play a little advertising, welcomed the focus on micro-channel scan code number public: "flat head brother of technical Bowen" progress together.
Scan code concerns

Guess you like

Origin www.cnblogs.com/jamaler/p/11421049.html