Singleton basic knowledge of Java and related interview questions

First, what is the embodiment of the single mode
single-mode embodiment is a common software design pattern, which is defined as the class of a single embodiment allows only one instance of the object exists.

Many times the entire system only need to have a global object, this will help us coordinate the overall behavior of the system. For example, in a server program, the server configuration information is stored in a file, the configuration data is read by a singleton object unity, then the other objects in the process of re-acquiring service configuration information through the singleton object. This approach simplifies the configuration management in complex environments.
Here Insert Picture Description
For single embodiment mainly through the following two steps:
the constructor for class 1. Definition of the private methods, so that the code can not be at the other instance of the class object by calling the constructor of the class, only through the class provides static methods to obtain the only instance of the class;
2. provide a static method in the class, when we call this method, if the class is not empty references held by this reference is returned, if the class held reference empty instance of the class is created and the reference to an instance of the class to keep the references given.
Second, the singleton application scenario
As an example, the website of the counter, are generally single embodiment mode implemented, if you present a plurality of counters, each user access to all the refresh counter value, so the value of your real count it is difficult to synchronize. But if the Singleton pattern to achieve such a problem would not exist, but also to avoid thread-safety issues. Thread pool multithreaded designs are generally the same single-mode embodiment, this is due to the need to facilitate the thread pool thread pool control

Similarly, for some log application reads the configuration file of the application, or web are suitable for use in the development of single-mode embodiment, as is typical application HttpApplication single embodiment.
From the above examples we can conclude that for single mode embodiment scenes and disadvantages:
Application scenario:
1. The need to generate a unique sequence environment
2. frequently instantiate the object and then destroyed.
3. When you create an object too time-consuming or consuming too many resources, but frequently used objects.
4. Environment communication resources to facilitate mutual
disadvantages three singletons
advantages:
1. only one object in memory, save memory space;
2. avoid frequent create destroying objects, can improve performance;
3. To avoid the shared resource multiple occupancy, simplify access;
4. to provide a global point of access for the entire system.
Cons:
1. The change does not apply to frequent subject;
2. a single case of abuse will bring some negative issues, in order to save resources such as database connection pool object as a singleton class design, may lead to an object through a shared connection pool multi connection pool overflow occurs;
; 3. If the instantiation object for a long time is not utilized, the system will refuse the object is considered to be recovered, which may cause the loss of the object state
four patterns to achieve the single Example
1. hungry Chinese-style

// 饿汉式单例
public class Singleton1 {
 
    // 指向自己实例的私有静态引用,主动创建
    private static Singleton1 singleton1 = new Singleton1();
 
    // 私有的构造方法
    private Singleton1(){}
 
    // 以自己实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton1 getSingleton1(){
        return singleton1;
    }
}

We know that the way the class loader is loaded on demand, and loaded once. . Therefore, when the above singleton class is loaded, it will instantiate an object and give your own reference, used by the system; and, because of this class throughout the life cycle will only be loaded once, and therefore will only create an instance , i.e., a single case can be sufficiently guaranteed.
Advantages: such an approach is relatively simple, that is, when the loading is completed the class is instantiated. To avoid the thread synchronization issues.
Disadvantage: when the class is instantiated loading is completed, the effect did not reach the Lazy Loading. If you have never used this example from start to finish, it will result in a waste of memory.
2. lazy style

// 懒汉式单例
public class Singleton2 {
 
    // 指向自己实例的私有静态引用
    private static Singleton2 singleton2;
 
    // 私有的构造方法
    private Singleton2(){}
 
    // 以自己实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton2 getSingleton2(){
        // 被动创建,在真正需要使用时才去创建
        if (singleton2 == null) {
            singleton2 = new Singleton2();
        }
        return singleton2;
    }
}

We can see from the lazy man singleton, singleton instance is lazy loading, that is, only when you actually use will instantiate an object and handed over to their references.

The wording has played a Lazy Loading effect, but can only be used in single-threaded. If, in multi-threaded, a thread into the if (singleton == null) Analyzing statement block, had time to perform down, but also by another thread Analyzing this statement will produce a plurality of time instances. So in a multithreaded environment can not be used in this way .

Hungry and lazy style of Han difference?
1, thread-safe:
a hungry man is inherently thread-safe type, can be used directly for multi-threaded without problems, lazy style itself is not thread-safe
2, resource loading and performance:
hungry Chinese-style class at the same time created a static object to instantiate it, regardless of later will use this single example, will occupy a certain memory, but appropriate, at the time of the first call speed will be faster, because of its resources initialization has been completed,
while the lazy man's name suggests, it will delay loading, will instantiate an object at the time of first use of the singleton out, do initialize the first call, if more work to be done, the performance will be some delay, and after just a hungry man style the same.
3. The dual locking mechanism

public class Singleton
    {
        private static Singleton instance;
        //程序运行时创建一个静态只读的进程辅助对象
        private static readonly object syncRoot = new object();
        private Singleton() { }
        public static Singleton GetInstance()
        {
            //先判断是否存在,不存在再加锁处理
            if (instance == null)
            {
                //在同一个时刻加了锁的那部分程序只有一个线程可以进入
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

Double-Check concept for multi-threaded developers will not be unfamiliar, as shown in the code, we conducted two if (singleton == null) examination, so as to ensure the security thread. Thus, with examples of code is executed only once, when accessed again later, it is judged if (singleton == null), the direct return object instance.

Dual synchronous detection using lazy loading approach to create a single case is a very good approach, not only to ensure that a single case, and effectively improve the operating efficiency program

Pros: thread-safe; lazy loading; high efficiency.
4. static initialization

//阻止发生派生,而派生可能会增加实例
    public sealed class Singleton
    {
        //在第一次引用类的任何成员时创建实例,公共语言运行库负责处理变量初始化
        private static readonly Singleton instance=new Singleton();
        
        private Singleton() { }
        public static Singleton GetInstance()
        {
            return instance;
        }
    }

Of course, implementation of the single-mode embodiment as well. However, these four is more classic achieve, is what we should have achieved in several ways.
Four methods of achieving this, we can conclude that, in order to achieve high efficiency thread-safe singleton, we must note the following points:
to minimize the scope of sync blocks;
to make use of fine-grained locks.

Added: static inner classes seem to seem to have the most perfect way, but in fact is not, there may also be reflective of an attack or counter-attack sequence. Let us look at the following code:
① reflection attacks:

public static void main(String[] args) throws Exception {
    Singleton singleton = Singleton.getInstance();
    Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Singleton newSingleton = constructor.newInstance();
    System.out.println(singleton == newSingleton);
}

Run the result is false

② deserialization attacks:

public class Singleton implements Serializable {

    private static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }

    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        byte[] serialize = SerializationUtils.serialize(instance);
        Singleton newInstance = SerializationUtils.deserialize(serialize);
        System.out.println(instance == newInstance);
    }
}

Run the result is false

Therefore, embodiments may be single-mode enumeration. Avoid these problems

public enum Singleton {

    INSTANCE;

    public void doSomething() {
        System.out.println("doSomething");
    }
}
public class Main {

    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}

It can directly call through Singleton.INSTANCE.doSomething () way. Convenient, simple and safe.

Spring is a single embodiment of the bean, Servlet also a single embodiment.

Published 99 original articles · won praise 2 · Views 2629

Guess you like

Origin blog.csdn.net/weixin_41588751/article/details/105103516