Application scenario
Only one instance is required. In terms of code and memory, only one instance is required
Key points
First, the construction method is designed to be private
Unable to new
Second: provide a method to obtain an instance
Related concepts
1.class.forName("") can load the class name. When the static variable is loaded into memory, it will be instantiated
2. The same hash code is not necessarily the same object
3. Variables modified by final Must initialize
Writing related
Hungry Han style
Advantages: when a class is loaded into memory, it instantiates a simple jvm to ensure thread safety, which is simple and practical
Disadvantages: no matter whether it is used or not, the instantiation is completed when the class is loaded
Code block
public class Single1 { private static final Single1 INSTANCE = new Single1(); private Single1() {}; public static Single1 getINSTANCE() { return INSTANCE; } public void m() {System.out.println("m");} public static void main(String[] args) { Single1 m1 = Single1.getINSTANCE(); Single1 m2 = Single1.getINSTANCE(); System.out.println(m1 == m2); } }
Lazy style
Advantages: the purpose of loading on demand is achieved
Disadvantages: it brings the problem of thread insecurity
Code block
public class Single2 { //If final is added, it must be initialized private static Single2 INSTANCE; private Single2() {} public static Single2 getINSTANCE() { if (INSTANCE == null) { try { //Sleeping for a millisecond will produce different instantiated instances of the object Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Single2(); } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for (int i=0; i<100; i++) { new Thread(()-> { System.out.println(Single2.getINSTANCE().hashCode()); //Different objects have different hash codes }).start(); } } }
The following code snippets are the advanced version of hungry Chinese style
In addition, synchronized locks the current statement block, but the efficiency is reduced
Code block
public class Single3 { //If final is added, it must be initialized private static Single3 INSTANCE; private Single3() {} //Locking every time reduces the efficiency public static synchronized Single3 getINSTANCE() { if (INSTANCE == null) { try { //Sleeping for a millisecond will produce different instantiated instances of the object Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Single3(); } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for (int i=0; i<100; i++) { new Thread(()-> { System.out.println(Single3.getINSTANCE().hashCode()); //Different objects have different hash codes }).start(); } } }
The efficiency is improved by reducing the synchronous code block, and the same instance can not be achieved in the case of multiple threads
Code block
public class Single4 { //If final is added, it must be initialized private static Single4 INSTANCE; private Single4() {} //Locking every time reduces the efficiency public static Single4 getINSTANCE() { if (INSTANCE == null) { synchronized (Single4.class) { try { //Sleeping for a millisecond will produce different instantiated instances of the object Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Single4(); } } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for (int i=0; i<100; i++) { new Thread(()-> { System.out.println(Single4.getINSTANCE().hashCode()); //Different objects have different hash codes }).start(); } } }
Double check single case judgment
Code block
public class Single5 { //If final is added, volatile must be initialized to prohibit instruction rearrangement private static volatile Single5 INSTANCE; private Single5() {} //Locking every time reduces the efficiency public static Single5 getINSTANCE() { if (INSTANCE == null) { synchronized (Single5.class) { //duplication check if (INSTANCE == null) { try { //Sleeping for a millisecond will produce different instantiated instances of the object Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Single5(); } } } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for (int i=0; i<100; i++) { new Thread(()-> { System.out.println(Single5.getINSTANCE().hashCode()); //Different objects have different hash codes }).start(); } } }
Static inner class mode
Relevant knowledge points:
1. The JVM guarantees that the singleton will not load the internal class when loading the external class, and lazy loading can be realized
2. Privatization. Only internal classes can be new
3. The internal class will not be loaded casually. It will be loaded only when it is called
4. When the virtual machine loads a class, it only loads it once
Code block
public class Single6 { private Single6() {} private static class Single6Holder { private final static Single6 INSTANCE = new Single6(); } public static Single6 getInstance() { return Single6Holder.INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for (int i=0; i<100; i++) { new Thread(()->{ System.out.println(Single6.getInstance().hashCode()); }).start(); } } }
Enumeration class mode
Relevant knowledge points:
1. It can not only solve thread synchronization, but also prevent deserialization
2. The singleton prevents deserialization, reflects the class, and load s it into memory
3. The reason why it will not be deserialized is that the enumeration class has no constructor. Even if it is deserialized, it will only get the value of the enumeration class
4. Grammar is the most perfect
Code block
public enum Single7 { INSTANCE; public void m() {} public static void main(String[] args) { for (int i=0;i<100; i++) { new Thread(()->{ System.out.println(Single7.INSTANCE.hashCode()); }).start(); } } }
relevant
bean factory in spring framework to guarantee singleton