In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "analyzing singleton patterns in Java". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "analyzing the singleton pattern in Java".
WHAT
Wikipedia gives explanations, ideas for implementation, and areas that should be noted:
Singleton pattern, also known as singleton pattern, is a commonly used software design pattern, which belongs to a kind of creative pattern. When applying this pattern, the class of the singleton object must ensure that only one instance exists.
The idea of implementing the singleton pattern is that a class can return an object with a reference (always the same) and a method that gets the instance (it must be a static method, usually using the name getInstance); when we call this method, we return the reference if the reference held by the class is not empty, create an instance of the class if the reference held by the class is empty, and assign the instance reference to the reference maintained by the class At the same time, we also define the constructor of the class as a private method, so that the code in other places can not instantiate the object of the class by calling the constructor of the class, but only through the static methods provided by the class.
Singleton mode must be used carefully in multithreaded applications. If two threads call the creation method at the same time when the unique instance has not been created, they do not detect the existence of the unique instance at the same time, so they each create one instance at the same time, so that two instances are constructed, thus violating the principle of instance uniqueness in the singleton pattern. The solution to this problem is to provide a mutex for variables indicating whether the class has been instantiated (although this reduces efficiency).
The class diagram is:
WHY
As the definition says, the singleton pattern is the entire memory model, with only one instance. With fewer instances, less memory is used. At the same time, there is only one instance, that is, only one object needs to be built, and there is less computation. For objects that require a lot of computation or take up a lot of resources in the construction process, creating them only once reduces the resource and memory footprint.
Hungry Han style
The hungry Han style is the simplest implementation, which completes the instantiation in the class loading process and avoids the problem of multithreading.
Implementation 1: static instance parameters and static code blocks
Public class EagerSingleton {private static final EagerSingleton INSTANCE = new EagerSingleton (); private EagerSingleton () {} public static EagerSingleton getInstance () {return INSTANCE;}}
According to the characteristics of java, elegance Han style can also be written in a variety of ways, which in some places is called static code block mode:
Public class EagerSingleton {private static EagerSingleton INSTANCE = null; static {INSTANCE = new EagerSingleton ();} private EagerSingleton () {} public static EagerSingleton getInstance () {return INSTANCE;}}
These two ways are only different in writing methods, and there is no difference in advantages and disadvantages, but with the help of the different writing methods of Java language features, so they are classified into one category.
The hungry Han style has two obvious disadvantages:
The class loading process completes the instantiation, and if the instance is not used throughout the application life cycle, it is a waste of resources.
Because there is no way to pass different parameters to the constructor, this approach is not supported if you need to customize the instance through personalized parameters.
Implementation 2: static inner class
In view of the first disadvantage of the hungry Han style, we can delay the instantiation of the object by means of static inner classes.
Public class EagerSingleton {private EagerSingleton () {} private static class EagerSingletonInstance {private static final EagerSingleton INSTANCE = new EagerSingleton ();} public static EagerSingleton getInstance () {return EagerSingletonInstance.INSTANCE;}}
However, the second disadvantage can not be well solved. If you need to implement different instances according to different parameters, you can use the lazy implementation described below.
Lazy style
One of the advantages of the lazy Chinese style over the hungry Chinese style is that it can be instantiated when it is used. However, the pie is always accompanied by traps, and there are more pits in the lazy style, which are accidentally dropped.
Error 1: single-threaded implementation
Public class LazySingleton {private static LazySingleton INSTANCE = null; private LazySingleton () {} public static LazySingleton getInstance () {if (INSTANCE = = null) {INSTANCE = new LazySingleton ();} return INSTANCE;}}
It is defined as a single-threaded implementation because of the judgment of INSTANCE==null, through which a thread begins to instantiate an object, but before the instantiation is completed, another thread comes. At this time, before the object is instantiated, it will also begin to instantiate, resulting in unnecessary waste.
Error 2: synchronization method
Public class LazySingleton {private static LazySingleton INSTANCE = null; private LazySingleton () {} public static synchronized LazySingleton getInstance () {if (INSTANCE = = null) {INSTANCE = new LazySingleton ();} return INSTANCE;}}
This approach solves the problem of multithreading, but also introduces a new performance problem: too slow. Synchronized wraps the whole method, that is, when each thread enters, it needs to wait for other threads to finish the call before getting the instance, which is fatal in performance-sensitive scenarios.
Error 3: single check of synchronous code block
Public class LazySingleton {private static LazySingleton INSTANCE = null; private LazySingleton () {} public static LazySingleton getInstance () {if (INSTANCE = = null) {synchronized (LazySingleton.class) {INSTANCE = new LazySingleton ();}} return INSTANCE;}}
This kind of writing seems to reduce the synchronization code, but it also reduces the guarantee of multithreading, and also makes the mistake of the first way of writing, which belongs to the low-level error code written without a basic understanding of multithreading.
Error 4: double checking of synchronous code blocks
Public class LazySingleton {private static LazySingleton INSTANCE = null; private LazySingleton () {} public static LazySingleton getInstance () {if (INSTANCE = = null) {synchronized (LazySingleton.class) {if (INSTANCE = = null) {INSTANCE = new LazySingleton ();} return INSTANCE;}}
This writing method belongs to the correct writing method to a certain extent, and double judgment can well achieve thread safety and delayed loading. If it ends here, it will be an error of a thousand miles.
There is nothing wrong with double checking and synchronizing code blocks, but the problem lies in the sentence INSTANCE=newLazySingleton (). In JVM, to make full use of CPU's computing power, reordering optimization is done, and INSTANCE=newLazySingleton () does three things:
Initialize stack space for INSTANCE
Allocate memory space for LazySingleton and instantiate objects
INSTANCE points to the memory space allocated by the LazySingleton instance
Because of the existence of reordering optimization, there may be a 1-2-3 order or a 1-3-2 order during the actual execution. If 1-3-2 LazySingleton instance points to the memory space allocated by the LazySingleton instance, it is not null. When another thread enters to judge the INSTANCE, it will return INSTANCE directly, but at this time the instantiation of the LazySingleton has not been completed, an unexpected exception may occur.
Correct: double check + prevent reordering
Public class LazySingleton {private static volatile LazySingleton INSTANCE = null; private LazySingleton () {} public static LazySingleton getInstance () {if (INSTANCE = = null) {synchronized (LazySingleton.class) {if (INSTANCE = = null) {INSTANCE = new LazySingleton ();} return INSTANCE;}}
This way of writing is better than the one above, except for the keyword volatile.
Enumerate
Both lazy and hungry can be used in multithreaded concurrency scenarios, but objects can be instantiated through deserialization or reflection, which still can not meet the requirements of singleton mode, so enumerations can be implemented with the help of enumerations. enumeration can perfectly avoid the problem of multithreaded concurrency and prevent deserialization and reflection from creating new objects. When I first saw this definition of singleton pattern, it was in "Effective Java" that it was good to read more classic books.
Public enum EnumSingleton {INSTANCE; public void method1 () {/ / do something} public Object method2 () {/ / do something and return something else return new Object ();}
In development practice, enumeration can satisfy most scenarios, and the writing method is simple, the logic of defining singleton only needs three lines of code, which is concise but not simple, and three lines of code can ensure thread safety. At the same time, the deserialization of enumerations only looks for objects through name and does not produce new objects; according to the JVM specification, when an enumerated object is created by reflection, an IllegalArgumentException exception is thrown. In this way, it is equivalent to preventing deserialization and reflection from destroying singletons through syntax sugar.
Scene
Stateless tool class: this tool class does not need to record status, just ensures the correct application, and can be defined by singleton mode.
Data sharing: communication between multiple unrelated threads or processes. Because it is an instance, if its property or variable value is modified, all references are modified at the same time, of course, volatile is needed to define the variable. Such as the counter of the website.
Log application: usually the application will write log information to the log file. In order to write to the file in real time, the singleton mode is usually used to ensure that an instance holds the file and then operates.
Database connection pool: database connection is a kind of database resource. Using database connection pool is mainly to save the efficiency loss caused by opening or closing database connection. This efficiency loss is still very expensive. Through singleton mode maintenance, this loss can be greatly reduced.
Configuration objects for Web applications: it takes time to read files, and it takes longer to read large files, so singleton mode can greatly reduce consumption.
. . .
There are still many scenarios of singleton mode. Here are just a few simple application scenarios listed here, which can be regarded as throwing a brick to attract jade. If officials have any other application scenarios, you can talk about them again.
At this point, I believe you have a deeper understanding of "analyzing the singleton pattern in Java". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.