The difference between java singleton mode is: 1. Once the hungry man's class is loaded, the singleton initialization is completed. The singleton already exists, while the lazy man only goes back to initialize this when he calls getInstance. Singleton; 2. The hungry style is inherently thread-safe, while the lazy style itself is not thread-safe.
[Related learning recommendations: java basic tutorial】
Differences in java singleton mode Yes:
1. Lazy Singleton
//懒汉式单例类.在第一次调用的时候实例化自己 public class Singleton { private Singleton() {} private static Singleton single=null; //静态工厂方法 public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } }
Singleton avoids the class from being externally accessed by limiting the constructor to private. Instantiation, within the scope of the same virtual machine, the only instance of Singleton can only be accessed through the getInstance() method.
(In fact, through the Java reflection mechanism, it is possible to instantiate a class with a private constructor, which will basically invalidate all Java singleton implementations. This issue will not be discussed here. Let’s hide our ears for the time being. It is believed that the reflection mechanism does not exist.)
However, the above lazy-style singleton implementation does not consider thread safety issues. It is thread unsafe. Multiple Singleton instances are likely to appear in a concurrent environment. To achieve thread safety, , there are the following three methods, all of which modify the getInstance method to ensure the thread safety of lazy-style singletons. If you are exposed to the singleton mode for the first time and do not know much about thread safety, you can skip the following three tips first. Article, take a look at the Hungry-style singleton, and then go back and consider the issue of thread safety after reading it:
1. Add synchronization to the getInstance method
public static synchronized Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; }
2. Double check locking
public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; }
3. Static inner class
public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
This is better than the above 1 and 2. It not only achieves thread safety, but also avoids the performance impact caused by synchronization.
2. Hungry Han Style Singleton
//饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //静态工厂方法 public static Singleton1 getInstance() { return single; } }
Hungry Han Style has already created a static object for system use when the class is created, and will not change it in the future. , so it is inherently thread-safe.
3. Registered singleton (can be ignored)
//类似Spring里面的方法,将类名注册,下次从里面直接获取。 public class Singleton3 { private static Map<String,Singleton3> map = new HashMap<String,Singleton3>(); static{ Singleton3 single = new Singleton3(); map.put(single.getClass().getName(), single); } //保护的默认构造子 protected Singleton3(){} //静态工厂方法,返还此类惟一的实例 public static Singleton3 getInstance(String name) { if(name == null) { name = Singleton3.class.getName(); System.out.println("name == null"+"--->name="+name); } if(map.get(name) == null) { try { map.put(name, (Singleton3) Class.forName(name).newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return map.get(name); } //一个示意性的商业方法 public String about() { return "Hello, I am RegSingleton."; } public static void main(String[] args) { Singleton3 single3 = Singleton3.getInstance(null); System.out.println(single3.about()); } }
The registered singleton actually maintains a set of instances of the singleton class and stores these instances in In a Map (registration book), for instances that have been registered, they are returned directly from the Map. For those that are not registered, they are registered first and then returned.
Here I have marked the registration-style singleton as negligible. From my understanding, first of all, it is used less often. In addition, the internal implementation still uses the Hungry-style singleton because of the static method block in it. , its singleton is instantiated when the class is loaded.
4. The difference between the Hungry Man style and the Lazy Man style
In terms of name, Hungry Man and Lazy Man,
Hungry Han means that once the class is loaded, the singleton is initialized to ensure that the singleton already exists when getInstance is called.
The lazy man is lazy and only goes back to initialize the singleton when getInstance is called. .
In addition, we can distinguish the following two methods from the following two points:
1. Thread safety:
Hungry Chinese style is inherently thread-safe. , can be used directly for multi-threading without problems.
The lazy style itself is not thread-safe. In order to achieve thread safety, there are several writing methods, namely 1, 2, and 3 above. These three implementations There are some differences in resource loading and performance.
2. Resource loading and performance:
Hungry Chinese style instantiates a static object when the class is created. Regardless of whether this singleton will be used later, it will occupy a certain amount of memory. , but correspondingly, the speed will be faster when it is called for the first time, because its resources have been initialized,
and the lazy style, as the name suggests, will delay loading, and will only load it when the singleton is used for the first time. The object will be instantiated and initialized when called for the first time. If there is a lot of work to be done, there will be some delay in performance, and then it will be the same as the hungry Chinese style.
As for the three implementations 1, 2, and 3, there are some differences.
The first type adds synchronization to the method call. Although it is thread safe, it must be synchronized every time. It will affect performance. After all, synchronization is not required in 99% of cases.
The second type is to do two null checks in getInstance to ensure that it will only be done when the singleton is called for the first time. Synchronization, this is also thread-safe, and avoids the performance loss of synchronization every time
The third method uses the classloader mechanism to ensure that there is only one thread when initializing the instance, so it is also thread-safe, and there is no Performance loss, so generally I tend to use this one.
Related learning recommendations: Programming video
The above is the detailed content of What are the differences between java singleton patterns?. For more information, please follow other related articles on the PHP Chinese website!