Design mode 01-- singleton

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/Papaya_shun/article/details/91359249

A classification (Group Of Four / GOF 23)

Design Mode must be applied to specific applications.
Create a schema: singleton, factory pattern, abstract factory pattern, the creator mode, the prototype model.
Structured Mode: adapter mode, bridge mode, decorative patterns, combined mode, the appearance model, Flyweight, proxy mode.
Behavioral patterns: template method pattern, command mode, the iterator pattern, observer pattern, intermediary model, the memo mode, the interpreter pattern, state pattern, strategy pattern, chain of responsibility pattern, the visitor pattern.

Second, singleton

  • Action
    to ensure that only one object of a class, and provides access to the instance of a global access point.

  • Scenarios
    task manager, configuration files, log management, database connection pool, OS file system, Application objects in the Servlet, Spring in the Bean.

  • The advantages of
    memory footprint and less system overhead.

  • Achieved
    mainly:
    (1) a hungry man type
    constructor private, (thread-safe natural process) when the class is initialized to load the objects (static).
    Thread-safe, high-efficiency calls, the delay can not be loaded.

/**
 * 饿汉式单例模式
 */
class SingletonPattern01 {

    // 类加载时对象就创建了
    private static /*final*/ SingletonPattern01 instance = new SingletonPattern01();

    private SingletonPattern01() {
    }

    public static SingletonPattern01 getInstance() {
        return instance;
    }
}

(2) lazy man
lazy loading, when needed to load, but need to consider synchronization synchronized.
Thread-safe, high resource utilization, latency load, concurrent low efficiency.

/**
 * 懒汉式单例模式
 */
class SingletonPattern02 {

    private static SingletonPattern02 instance;

    private SingletonPattern02() {
    }

    // 延时加载
    public static synchronized SingletonPattern02 getInstance() {
        if (instance == null) {
            instance = new SingletonPattern02();
        }
        return instance;
    }
}

Other:
(3) detecting the double-lock (due to the underlying JVM internal model, problems occasionally, not recommended)
synchronization method for the optimization of two sync blocks, placed inside if.
Problems: 1. The strength of the object can be divided into memory space is allocated; 2 initializes the object; 3 points to the memory space object just assigned... Some compilers for performance issues may reorder the steps 2 and 3, resulting in one thread to access the object's memory space has been allocated, the object is not yet completed the initialization occurred.
Resolution: The volatile keyword to the object, the object will be stored in memory rather than the cache.

/**
 * 双重检测锁式单例模式
 */
class SingletonPattern03 {

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

    private SingletonPattern03() {

    }

    public static SingletonPattern03 getInstance(){
        // 提高检测效率
        if (instance == null) {
            synchronized (SingletonPattern03.class) {
                // 可能有多线程同时进入同步块内
                if (instance == null) {
                    instance = new SingletonPattern03();
                }
            }
        }
        return instance;
    }
}

(4) static inner class type (thread-safe, high-efficiency calls, delay load)
to optimize Note: thread-safe, high call efficiency, lazy loading
to load static inner classes do not need to attach an external class, when loaded in use, but in the process of loading a static inner class will also load external classes.

/**
 * 静态内部类式单例模式
 */
class SingletonPattern04 {

    // 静态内部类在使用时加载,天然线程安全
    private static class SingletonPatternClassInstance {
        // 保证只有一个,且只能赋值一次
        private static final SingletonPattern04 instance = new SingletonPattern04();
    }

    public static SingletonPattern04 getInstance() {
        return SingletonPatternClassInstance.instance;
    }

    private SingletonPattern04() {
    }
}

problem: Even if the constructor private, and can be invoked through reflection.

(5) enumerated singleton (thread-safe, high-efficiency calls, the delay can not be loaded)
can prevent reflection of natural and deserialization, based on the underlying implementation of the JVM. 4,5 better.

/**
 * 枚举式单例模式
 */
enum SingletonPattern05 {

    // 枚举元素本身就是单例的,INSTANCE就是SingletonPattern05的一个单例
    INSTANCE;

    // 添加需要的操作
    public void singletonPatternOperation() {

    }
}
  • Reflective cracking
    by c.setAccessible(true);protective skipping private constructor.
public static void main(String[] args) throw Exception {
	Class<SingletonPattern01> clazz = (Class<SingletonPattern01>) Class.forName("com.ustc.designpattern.SingletonPattern01");
	Constructor<SingletonPattern01> c = clazz.getDeclaredConstructor(null);
	c.setAccessible(true);
	SingletonPattern01 s3 = c.newInstance();
	SingletonPattern01 s4 = c.newInstance();
}

Resolution: The determination, the reflector throws an exception operation when the private constructor.

private SingletonPattern01() {
 	if (instance != null) {
        throw new RuntimeException();
    }
}
  • Deserialization break
public static void main(String[] args) throw Exception {
	FileOutputStream fos = new FileOutputStream("${url}");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(s1);
    oos.close();
    fos.close();

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("${url}"));
    SingletonPattern01 s5 = (SingletonPattern01) ois.readObject();
}

Solution: define readResolve () method, this method of direct return deserialize objects without the need to create new

private Object readResolve() throw ObjectStreamException {
	return instance;
}
  • Performance Comparison
  • Here Insert Picture Description
    CountDownLatch:
    synchronization aid before completing a set of operations being performed by other threads, which allows one or more threads have been waiting for.
    coutDown () the current thread calls this method, the count by one, finally put in execution;
    the await (), calling this method blocks until the current process, know the timer value is zero.

Guess you like

Origin blog.csdn.net/Papaya_shun/article/details/91359249