当前位置:网站首页>A thorough understanding of singleton
A thorough understanding of singleton
2022-06-22 14:41:00 【happysnaker】
The article has been included in my warehouse :Java Share your study notes with free books
Design motivation
As its name suggests , The singleton pattern ensures that a class has only one instance , So why do you need to design a singleton pattern ?
For some classes , Only one instance is important , For example, a computer should have only one file system , Manufacturers should not configure a computer with two file systems ; An application should have a dedicated log object , Instead of writing here and there for a while ; There is often only one thread pool in a program , Threads are managed by a thread pool , Instead of using multiple thread pools , That makes threads messy and difficult to maintain ; stay Abstract factory in , Only one factory class should exist …
Such requirements , We all need to ensure that a class has only one instance , At this point, you can use the singleton mode .
Design
We must prevent users from instantiating multiple objects , The solution is to let the class save its only instance , And hide the constructor , And expose a specific static method to return a unique instance , In this way, users will not be able to instantiate multiple objects by themselves, but can only obtain unique instances through static methods exposed by classes .
Code example
Suppose the requirements are as follows : The same log object is required in the global state of an application .
One 、 The sluggard model
Lazy mode does not initialize instances directly , Instead, wait until the instance is used before initializing it , Avoid unnecessary waste of resources .
// Log file class
class LogFile {
// The only example
private static LogFile logFile = null;
// The construction method is hidden from the outside
private LogFile(){
};
// Methods of exposure
public static LogFile getInstance() {
// The sluggard model
if (logFile == null) {
logFile = new LogFile();
}
return logFile;
}
}
public class Test {
public static void main(String[] args) {
var s1 = LogFile.getInstance();
var s2 = LogFile.getInstance();
System.out.println(s1 == s2); // Output true, The same object is generated
}
}
The code here works well in a single thread ,logFile Resources belonging to the critical zone , So this is not thread safe , The initial example is null, Threads A After execution if After the judgment sentence, execute logFile = new LogFile() Before being scheduled to the thread B, The thread B The instance you see is also empty , because A It's not initialized yet , So threads B Initialize instance , When returning to the thread A when , Threads A Construction will continue logFile The sentence of , here logFile It has been initialized twice , they A And B The obtained instance is not the same .
A simple solution is to lock them :
public static LogFile getInstance() {
synchronized (LogFile.class) {
// The sluggard model
if (logFile == null) {
logFile = new LogFile();
}
}
return logFile;
}
But the efficiency of locking is too low , It would be better to adopt the starving Han style , Because the instant when logFile Isn't empty , Multiple threads must also queue to get instances , In fact, there is no need to queue up , When logFile Isn't empty , Multiple threads should be able to get logFile example , Because they just read the instance and do not change it , Shared reads are thread safe .
A better solution is to use double check locking :
public static LogFile getInstance() {
if (logFile == null) {
synchronized (LogFile.class) {
// The sluggard model
if (logFile == null) {
logFile = new LogFile();
}
}
}
return logFile;
}
Judge by adding a weight to the outer layer , We have solved the problems mentioned above , Now the code is efficient enough —— Locking is only involved at the very beginning .
Be careful , The above code is still thread unsafe , If you want thread safety , We have to logFile Instance declaration plus volatile keyword , namely :
private volatile static LogFile logFile;
To understand this , We must understand new The process of an object , The general process is as follows :
- Apply for memory space , Use default initialization for fields in the space ( The object is null).
- Call the constructor of the class , To initialize ( The object is null).
- The return address ( After execution, the object is not null).
If not volatile keyword ,Java The virtual machine may have instruction rearrangement under the premise of ensuring serialization , That is, the virtual machine may execute the first step 3 Proceed to step 2 Step ( Relatively rare ), When initializing objects, the virtual machine only considers the single thread situation , At this point, the instruction rearrangement does not affect the single thread operation , So in order to speed up , Instruction rearrangement is possible .
From the perspective of multithreading , If an instruction rearrangement occurs , Threads A stay new Object to execute the first part and then the third step , The object is no longer null 了 , But the object hasn't been constructed yet , Although this time the thread A And hold the lock , But this pair of threads B It has no effect —— Threads B The object of intrusion discovery is not null Instead, take away an object instance that has not been completely constructed —— You will not apply for a lock through the first level of judgment .
add volatile Keywords guarantee visibility and prevent instruction rearrangement .
But from a problem-solving point of view , We have a better solution —— Static inner class :
// Log file class
class LogFile {
// The instance is kept by the static inner class
private static class LazyHolder {
private static LogFile logFile = new LogFile();
}
// The construction method is hidden from the outside
private LogFile(){
};
// Methods of exposure
public static LogFile getInstance() {
return LazyHolder.logFile;
}
}
public class Test {
public static void main(String[] args) {
var s1 = LogFile.getInstance();
var s2 = LogFile.getInstance();
System.out.println(s1 == s2); // Output true, The same object is generated
}
}
Static inner classes work best , Static inner classes are loaded only when their member variables or methods are referenced , That is to say, the instance will be initialized only when we access the class for the first time , We delegate the instance to the static inner class to help initialize , The loading of static inner classes by virtual machines is thread safe , We avoid using locking mechanisms to delegate to virtual machines , This efficiency is very high .
Lazy style can avoid the generation of useless garbage objects —— It is initialized only when they are used , But we must also write more code to ensure its security , If a class is not very common , Using lazy style can save resources to a certain extent .
Two 、 Hungry Chinese style
The starving mode initializes the singleton when it is loaded , Enable the instance to be initialized when the user obtains it .
// Log file class
class LogFile {
// The only example
private static LogFile logFile = new LogFile();
// The construction method is hidden from the outside
private LogFile(){
};
// Methods of exposure
public static LogFile getInstance() {
return logFile;
}
}
public class Test {
public static void main(String[] args) {
var s1 = LogFile.getInstance();
var s2 = LogFile.getInstance();
System.out.println(s1 == s2); // Output true, The same object is generated
}
}
Starved Chinese is thread safe , because logFile Has been initially completed , Therefore, the hungry type is more efficient than the lazy type , But at the same time , If the instance is not used globally , The hungry man model will generate garbage and consume resources .
Summary of advantages and disadvantages
The main advantages :
Provides controlled access to unique instances .
There is only one object in the system , Save system resources .
Singleton mode allows a variable number of instances .
Main drawback :
Poor scalability .
Singleton class , Too much responsibility , To a certain extent " Principle of single responsibility ".
Abusing a singleton will cause some negative problems , For example, in order to save resources, the database connection pool object is designed as a singleton class , Connection pool overflow may occur due to too many programs sharing connection pool objects ( Everyone uses a pool , Maybe the pool can't bear it ), If the instantiated object is not used for a long time, the system will be regarded as garbage object and recycled , This will result in the loss of object state .
边栏推荐
- Basic usage and FAQs of jasperreport report report generation tool
- 验证码是自动化的天敌?看看大神是怎么解决的
- JasperReport报表生成工具的基本使用和常见问题
- Seven cattle cloud upload picture
- Shan Zhiguang, chairman of BSN Development Alliance: DDC can provide the underlying support for the development of China's meta universe industry
- d的破坏与安全
- Cosmos、Polkadot
- Screenshot of the uniapp app and save it locally
- Error: unable to find a match: lrzsz
- C # WinForm photo album function, picture zooming, dragging, preview Pagination
猜你喜欢

Cve - 2022 - 22965 Resume

How to add a mask to a VR panoramic work? What is the function?

3DMAX modeling notes (I): introducing 3DMAX and creating the first model Hello World

Shan Zhiguang, chairman of BSN Development Alliance: DDC can provide the underlying support for the development of China's meta universe industry

Rongyun: let the bank go to the "cloud" easily

能让Jellyfin直接挂载阿里云盘的aliyundrive-fuse

Flink状态管理

Neuron+ekuiper realizes data collection, cleaning and anti control of industrial Internet of things

芯片硅片与流片技术

How location coding (PE) works in transformers
随机推荐
Cat agile team coaching workshops - August 20
transformers VIT图像模型向量获取
Cve - 2022 - 22965 Resume
C generic_ Generic class
Unity 子线程调用主线程的UI
Groovy之列表操作
Flink状态管理
Data collection: skillfully using Bloom filter to extract data summary
How to implement interface exception scenario testing? Exploration of test methods and implementation of test tools
In 5g era, how to create an amazing live VR activity?
unity和C#中怎么去比较2个日期大小
How to protect WordPress websites from cyber attacks? It is important to take safety measures
Sikulix select the picture of relative position (advanced version)
Biden signs two new laws aimed at strengthening government cyber security
Quickly understand the commonly used symmetric encryption algorithm, and no longer have to worry about the interviewer's thorough inquiry
Support vector machine for machine learning
如何理解fold change?倍数分析?
Kubernetes monitoring: grafana adds datasource and dashboard through automation
Fluentd is easy to get started. Combined with the rainbow plug-in market, log collection is faster
JS高级程序设计第 4 版:迭代器的学习