- 浏览: 758528 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (663)
- Eclipse&MyEclipse (40)
- PHP (3)
- Java (72)
- CSS (3)
- MySQL (35)
- Oracle (68)
- Red Hat Linux (23)
- Tomcat (26)
- Oracle10gAS (1)
- Spring (28)
- MyBatis&iBatis (13)
- JS (47)
- JQuery (23)
- Editplus (2)
- 其他 (4)
- Html (15)
- SQL (5)
- Ant (2)
- Hadoop (2)
- Servlet (9)
- Windows (11)
- Flex (1)
- CentOS Linux (7)
- Microsoft SQL Server (2)
- DB2 (3)
- Mysql char 与 varchar 区别 (0)
- excel (5)
- jsp (8)
- FreeMarker (1)
- EasyUI (5)
- WebShpere MQ (1)
- Maven2 (6)
- 浏览器缓存 (2)
- visio (1)
- XML (2)
- 物联网 (1)
- Maven (3)
- JSTL (2)
- HTTP (1)
- Fourinone (1)
- IP知识 (1)
- MyBatis (1)
- 项目管理 (2)
- office2003+2007 (1)
- DOS (1)
- JProfiler (1)
- Thinpad T440p (1)
- ActiveMQ (10)
- MongoDB (5)
- Vert.x3 (1)
- Ngnix (3)
- Spark (2)
- BigData (1)
- 性能概念公式 (1)
- RocketMQ (3)
- IT名词术语 (1)
- Java编程工具 (1)
- RabbitMQ (2)
- MetaMQ (1)
- 架构 (6)
- KafkaMQ (7)
- Redis (4)
- OAuth (1)
- Gradle (1)
- CentOS (5)
- Microsoft_Toolkit (1)
- git (5)
- IntelliJ Idea (4)
- Nginx (3)
- docker (12)
- VMware (2)
- 算法 (1)
- JDBCPool (1)
- spring-cloud (7)
- netbean (1)
- 微信小程序 (2)
- CURL (2)
- Java生成二维码 (1)
- 区块链 (2)
- 机器学习 (1)
- SpringBoot (3)
- Android (9)
- 微服务架构 (1)
- Kubernetes (2)
- OpenProject (0)
- 测试 (1)
- https (1)
- 开源许可证 (1)
- ServiceMesh (2)
- NET (0)
- .NET (1)
- TEST (1)
- iOS (2)
- thymeleaf (4)
- lombok (1)
- 浏览器设置 (1)
- 富文本编辑器 (1)
- 搜索引擎 (1)
- IT常识 (1)
- UML (0)
- Axure (1)
- appstore无法联网 (0)
- apk无法安装 (1)
- SQLServer (2)
- 卸载弹窗软件 (1)
- jenkins (1)
- TortoiseGit (1)
- eureka (1)
- ajax (1)
- spyder (0)
最新评论
Double-checked locking and the Singleton pattern
A comprehensive look at this broken programming idiom
Summary: All programming languages have their share of idioms. Many are useful to know and use, and programmers spend valuable time creating, learning, and implementing them. The problem is that some idioms are later proven not to be all that they were purported, or to simply not work as described. The Java programming language contains several useful programming idioms. It also contains some that further study has shown should not be used. Double-checked locking is one such idiom that should never be used. In this article, Peter Haggar examines the roots of the double-checked locking idiom, why it was developed, and why it doesn't work.
Date: 01 May 2002
Level: Intermediate
Comments: 10 (View | Add comment - Sign in) <!-- Rating_Area_Begin -->
Rate this article
<!-- dW_Summary_Area_END --><!-- CONTENT_BODY -->
Editor's note: This article refers to the Java Memory Model before it was revised for Java 5.0; statements about memory ordering may no longer be correct. However, the double-checked locking idiom is still broken under the new memory model. For more information on the memory model in Java 5.0, see "Java theory and practice: Fixing the Java Memory Model" Part 1 and Part 2.
The Singleton creation pattern is a common programming idiom. When used with multiple threads, you must use some type of synchronization. In an effort to create more efficient code, Java programmers created the double-checked locking idiom to be used with the Singleton creation pattern to limit how much code is synchronized. However, due to some little-known details of the Java memory model, this double-checked locking idiom is not guaranteed to work. Instead of failing consistently, it will fail sporadically. In addition, the reasons for its failure are not obvious and involve intimate details of the Java memory model. These facts make a code failure due to double-checked locking very difficult to track down. In the remainder of this article, we'll examine the double-checked locking idiom in detail to understand just where it breaks down.
To understand where the double-checked locking idiom originated, you must understand the common singleton creation idiom, which is illustrated in Listing 1:
Listing 1. Singleton creation idiom
import java.util.*; class Singleton { private static Singleton instance; private Vector v; private boolean inUse; private Singleton() { v = new Vector(); v.addElement(new Object()); inUse = true; } public static Singleton getInstance() { if (instance == null) //1 instance = new Singleton(); //2 return instance; //3 } } |
The design of this class ensures that only one Singleton
object is ever created. The constructor is declared private
and the getInstance()
method creates only one object. This implementation is fine for a single-threaded program. However, when multiple threads are introduced, you must protect the getInstance()
method through synchronization. If the getInstance()
method is not protected, it is possible to return two different instances of the Singleton
object. Consider two threads calling the getInstance()
method concurrently and the following sequence of events:
- Thread 1 calls the
getInstance()
method and determines thatinstance
isnull
at //1.
- Thread 1 enters the
if
block, but is preempted by thread 2 before executing the line at //2.
- Thread 2 calls the
getInstance()
method and determines thatinstance
isnull
at //1.
- Thread 2 enters the
if
block and creates a newSingleton
object and assigns the variableinstance
to this new object at //2.
- Thread 2 returns the
Singleton
object reference at //3.
- Thread 2 is preempted by thread 1.
- Thread 1 starts where it left off and executes line //2 which results in another
Singleton
object being created.
- Thread 1 returns this object at //3.
The result is that the getInstance()
method created two Singleton
objects when it was supposed to create only one. This problem is corrected by synchronizing the getInstance()
method to allow only one thread to execute the code at a time, as shown in Listing 2:
Listing 2. Thread-safe getInstance() method
public static synchronized Singleton getInstance() { if (instance == null) //1 instance = new Singleton(); //2 return instance; //3 } |
The code in Listing 2 works fine for multithreaded access to the getInstance()
method. However, when you analyze it you realize that synchronization is required only for the first invocation of the method. Subsequent invocations do not require synchronization because the first invocation is the only invocation that executes the code at //2, which is the only line that requires synchronization. All other invocations determine that instance
is non-null
and return it. Multiple threads can safely execute concurrently on all invocations except the first. However, because the method is synchronized
, you pay the cost of synchronization for every invocation of the method, even though it is only required on the first invocation.
In an effort to make this method more efficient, an idiom called double-checked locking was created. The idea is to avoid the costly synchronization for all invocations of the method except the first. The cost of synchronization differs from JVM to JVM. In the early days, the cost could be quite high. As more advanced JVMs have emerged, the cost of synchronization has decreased, but there is still a performance penalty for entering and leaving a synchronized
method or block. Regardless of the advancements in JVM technology, programmers never want to waste processing time unnecessarily.
Because only line //2 in Listing 2 requires synchronization, we could just wrap it in a synchronized block, as shown in Listing 3:
Listing 3. The getInstance() method
public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { instance = new Singleton(); } } return instance; } |
The code in Listing 3 exhibits the same problem as demonstrated with multiple threads and Listing 1. Two threads can get inside of the if
statement concurrently when instance
is null
. Then, one thread enters the synchronized
block to initialize instance
, while the other is blocked. When the first thread exits the synchronized
block, the waiting thread enters and creates another Singleton
object. Note that when the second thread enters the synchronized
block, it does not check to see if instance
is non-null
.
To fix the problem in Listing 3, we need a second check of instance
. Thus, the name "double-checked locking." Applying the double-checked locking idiom to Listing 3 results in Listing 4.
Listing 4. Double-checked locking example
public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 if (instance == null) //2 instance = new Singleton(); //3 } } return instance; } |
The theory behind double-checked locking is that the second check at //2 makes it impossible for two different Singleton
objects to be created as occurred in Listing 3. Consider the following sequence of events:
- Thread 1 enters the
getInstance()
method.
- Thread 1 enters the
synchronized
block at //1 becauseinstance
isnull
.
- Thread 1 is preempted by thread 2.
- Thread 2 enters the
getInstance()
method.
- Thread 2 attempts to acquire the lock at //1 because
instance
is stillnull
. However, because thread 1 holds the lock, thread 2 blocks at //1.
- Thread 2 is preempted by thread 1.
- Thread 1 executes and because instance is still
null
at //2, creates aSingleton
object and assigns its reference toinstance
.
- Thread 1 exits the
synchronized
block and returns instance from thegetInstance()
method.
- Thread 1 is preempted by thread 2.
- Thread 2 acquires the lock at //1 and checks to see if
instance
isnull
.
- Because
instance
is non-null
, a secondSingleton
object is not created and the one created by thread 1 is returned.
The theory behind double-checked locking is perfect. Unfortunately, reality is entirely different. The problem with double-checked locking is that there is no guarantee it will work on single or multi-processor machines.
The issue of the failure of double-checked locking is not due to implementation bugs in JVMs but to the current Java platform memory model. The memory model allows what is known as "out-of-order writes" and is a prime reason why this idiom fails.
To illustrate the problem, you need to re-examine line //3 from Listing 4 above. This line of code creates a Singleton
object and initializes the variable instance
to refer to this object. The problem with this line of code is that the variable instance
can become non-null
before the body of the Singleton
constructor executes.
Huh? That statement might be contradictory to everything you thought possible, but it is, in fact, the case. Before explaining how this happens, accept this fact for a moment while examining how this breaks the double-checked locking idiom. Consider the following sequence of events with the code in Listing 4:
- Thread 1 enters the
getInstance()
method.
- Thread 1 enters the
synchronized
block at //1 becauseinstance
isnull
.
- Thread 1 proceeds to //3 and makes instance non-
null
, but before the constructor executes.
- Thread 1 is preempted by thread 2.
- Thread 2 checks to see if instance is
null
. Because it is not, thread 2 returns theinstance
reference to a fully constructed, but partially initialized,Singleton
object.
- Thread 2 is preempted by thread 1.
- Thread 1 completes the initialization of the
Singleton
object by running its constructor and returns a reference to it.
This sequence of events results in a period of time where thread 2 returned an object whose constructor had not executed.
To show how this occurs, consider the following pseudo code for the line: instance =new Singleton();
mem = allocate(); //Allocate memory for Singleton object. instance = mem; //Note that instance is now non-null, but //has not been initialized. ctorSingleton(instance); //Invoke constructor for Singleton passing //instance. |
This pseudo code is not only possible, but is exactly what happens on some JIT compilers. The order of execution is perceived to be out of order, but is allowed to happen given the current memory model. The fact that JIT compilers do just this makes the issues of double-checked locking more than simply an academic exercise.
To demonstrate this, consider the code in Listing 5. It contains a stripped-down version of the getInstance()
method. I've removed the "double-checkedness" to ease our review of the assembly code produced (Listing 6). We are interested only in seeing how the line instance=new Singleton();
is compiled by the JIT compiler. In addition, I've provided a simple constructor to make it clear when the constructor is run in the assembly code.
Listing 5. Singleton class to demonstrate out-of-order writes
class Singleton { private static Singleton instance; private boolean inUse; private int val; private Singleton() { inUse = true; val = 5; } public static Singleton getInstance() { if (instance == null) instance = new Singleton(); return instance; } } |
Listing 6 contains the assembly code produced by the Sun JDK 1.2.1 JIT compiler for the body of the getInstance()
method from Listing 5.
Listing 6. Assembly code produced from code in Listing 5
;asm code generated for getInstance 054D20B0 mov eax,[049388C8] ;load instance ref 054D20B5 test eax,eax ;test for null 054D20B7 jne 054D20D7 054D20B9 mov eax,14C0988h 054D20BE call 503EF8F0 ;allocate memory 054D20C3 mov [049388C8],eax ;store pointer in ;instance ref. instance ;non-null and ctor ;has not run 054D20C8 mov ecx,dword ptr [eax] 054D20CA mov dword ptr [ecx],1 ;inline ctor - inUse=true; 054D20D0 mov dword ptr [ecx+4],5 ;inline ctor - val=5; 054D20D7 mov ebx,dword ptr ds:[49388C8h] 054D20DD jmp 054D20B0 |
Note: To reference the lines of assembly code in the following explanation, I refer to the last two values of the instruction address because they all begin with 054D20
. For example, B5
refers to test eax,eax
.
The assembly code is produced by running a test program that calls the getInstance()
method in an infinite loop. While the program runs, run the Microsoft Visual C++ debugger and attach it to the Java process representing the test program. Then, break the execution and find the assembly code representing the infinite loop.
The first two lines of assembly code at B0
and B5
load the instance
reference from memory location 049388C8
into eax
and test for null
. This corresponds to the first line of the getInstance()
method in Listing 5. The first time this method is called, instance
is null
and the code proceeds to B9
. The code at BE
allocates the memory from the heap for the Singleton
object and stores a pointer to that memory in eax
. The next line, C3
, takes the pointer in eax
and stores it back into the instance reference at memory location 049388C8
. As a result, instance
is now non-null
and refers to a valid Singleton
object. However, the constructor for this object has not run yet, which is precisely the situation that breaks double-checked locking. Then at line C8
, the instance
pointer is dereferenced and stored in ecx
. Lines CA
and D0
represent the inline constructor storing the values true
and 5
into the Singleton
object. If this code is interrupted by another thread after executing line C3
but before completing the constructor, double-checked locking fails.
Not all JIT compilers generate the code as above. Some generate code such that instance
becomes non-null
only after the constructor executes. Both the IBM SDK for Java technology, version 1.3 and the Sun JDK 1.3 produce code such as this. However, this does not mean you should use double-checked locking in these instances. There are other reasons it could fail. In addition, you do not always know which JVMs your code will run on, and the JIT compiler could always change to generate code that breaks this idiom.
Double-checked locking: Take two
Given that the current double-checked locking code does not work, I've put together another version of the code, shown in Listing 7, to try to prevent the out-of-order write problem you just saw.
Listing 7. Attempting to solve the out-of-order write problem
public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 inst = new Singleton(); //4 } instance = inst; //5 } } } return instance; } |
Looking at the code in Listing 7 you should realize that things are getting a little ridiculous. Remember, double-checked locking was created as a way to avoid synchronizing the simple three-line getInstance()
method. The code in Listing 7 has gotten out of hand. In addition, the code does not fix the problem. Careful examination reveals why.
This code is trying to avoid the out-of-order write problem. It tries to do this by introducing the local variable inst
and a second synchronized
block. The theory works as follows:
- Thread 1 enters the
getInstance()
method.
- Because
instance
isnull
, thread 1 enters the firstsynchronized
block at //1.
- The local variable
inst
gets the value ofinstance
, which isnull
at //2.
- Because
inst
isnull
, thread 1 enters the secondsynchronized
block at //3.
- Thread 1 then begins to execute the code at //4, making
inst
non-null
but before the constructor forSingleton
executes. (This is the out-of-order write problem we just saw.)
- Thread 1 is preempted by Thread 2.
- Thread 2 enters the
getInstance()
method.
- Because
instance
isnull
, thread 2 attempts to enter the firstsynchronized
block at //1. Because thread 1 currently holds this lock, thread 2 blocks.
- Thread 1 then completes its execution of //4.
- Thread 1 then assigns a fully constructed
Singleton
object to the variableinstance
at //5 and exits bothsynchronized
blocks.
- Thread 1 returns
instance
.
- Thread 2 then executes and assigns
instance
toinst
at //2.
- Thread 2 sees that
instance
is non-null
, and returns it.
The key line here is //5. This line is supposed to ensure that instance
will only ever be null
or refer to a fully constructed Singleton
object. The problem occurs where theory and reality run orthogonal to one another.
The code in Listing 7 doesn't work because of the current definition of the memory model. The Java Language Specification (JLS) demands that code within a synchronized
block not be moved out of a synchronized
block. However, it does not say that code not in a synchronized
block cannot be moved into a synchronized
block.
A JIT compiler would see an optimization opportunity here. This optimization would remove the code at //4 and the code at //5, combine it and generate the code shown in Listing 8:
Listing 8. Optimized code from Listing 7
public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 //inst = new Singleton(); //4 instance = new Singleton(); } //instance = inst; //5 } } } return instance; } |
If this optimization takes place, you have the same out-of-order write problem we discussed earlier.
Another idea is to use the keyword volatile
for the variables inst
and instance
. According to the JLS (see Resources), variables declared volatile
are supposed to be sequentially consistent, and therefore, not reordered. But two problems occur with trying to use volatile
to fix the problem with double-checked locking:
- The problem here is not with sequential consistency. Code is being moved, not reordered.
- Many JVMs do not implement
volatile
correctly regarding sequential consistency anyway.
The second point is worth expanding upon. Consider the code in Listing 9:
Listing 9. Sequential consistency with volatile
class test { private volatile boolean stop = false; private volatile int num = 0; public void foo() { num = 100; //This can happen second stop = true; //This can happen first //... } public void bar() { if (stop) num += num; //num can == 0! } //... } |
According to the JLS, because stop
and num
are declared volatile
, they should be sequentially consistent. This means that if stop
is ever true
, num
must have been set to 100
. However, because many JVMs do not implement the sequential consistency feature of volatile
, you cannot count on this behavior. Therefore, if thread 1 called foo
and thread 2 called bar
concurrently, thread 1 might set stop
to true
before num
is set to 100
. This could lead thread 2 to see stop
as true
, but num
still set to 0
. There are additional problems with volatile
and the atomicity of 64-bit variables, but this is beyond the scope of this article. See Resources for more information on this topic.
The bottom line is that double-checked locking, in whatever form, should not be used because you cannot guarantee that it will work on any JVM implementation. JSR-133 is addressing issues regarding the memory model, however, double-checked locking will not be supported by the new memory model. Therefore, you have two options:
- Accept the synchronization of a
getInstance()
method as shown in Listing 2.
- Forgo synchronization and use a
static
field.
Option 2 is shown in Listing 10:
Listing 10. Singleton implementation with static field
class Singleton { private Vector v; private boolean inUse; private static Singleton instance = new Singleton(); private Singleton() { v = new Vector(); inUse = true; //... } public static Singleton getInstance() { return instance; } } |
The code in Listing 10 does not use synchronization and ensures that the Singleton
object is not created until a call is made to the static getInstance()
method. This is a good alternative if your objective is to eliminate synchronization.
You might wonder about the String
class given the issue of out-of-order writes and a reference becoming non-null
prior to the constructor executing. Consider the following code:
private String str; //... str = new String("hello"); |
The String
class is supposed to be immutable. However, given the out-of-order write problem we discussed previously, could that cause a problem here? The answer is it could. Consider two threads with access to the String str
. One thread could see the str
reference refer to a String
object in which the constructor has not run. In fact, Listing 11 contains code that shows this occurring. Note that this code breaks only with older JVMs that I tested. Both the IBM 1.3 and Sun 1.3 JVMs produce immutable String
s as expected.
Listing 11. Example of a Mutable String
class StringCreator extends Thread { MutableString ms; public StringCreator(MutableString muts) { ms = muts; } public void run() { while(true) ms.str = new String("hello"); //1 } } class StringReader extends Thread { MutableString ms; public StringReader(MutableString muts) { ms = muts; } public void run() { while(true) { if (!(ms.str.equals("hello"))) //2 { System.out.println("String is not immutable!"); break; } } } } class MutableString { public String str; //3 public static void main(String args[]) { MutableString ms = new MutableString(); //4 new StringCreator(ms).start(); //5 new StringReader(ms).start(); //6 } } |
This code creates a MutableString
class at //4 that contains a String
reference shared by two threads at //3. Two objects are created, StringCreator
and StringReader
, on two separate threads at lines //5 and //6, passing a reference to the MutableString
object. The StringCreator
class enters an infinite loop and creates String
objects with the value "hello" at //1. The StringReader
also enters an infinite loop and checks to see if the current String
object has the value "hello" at //2. If it doesn't, the StringReader
thread prints out a message and stops. If the String
class is immutable, you should never see any output from this program. The only way for StringReader
to see the str
reference to be anything other than a String
object with "hello" as its value is if the problem of out-of-order writes occurs.
Running this code on old JVMs like Sun JDK 1.2.1 results in the out-of-order write problem, and thus, a non-immutable String
.
In an effort to avoid costly synchronization in singletons, programmers, quite ingeniously, invented the double-checked locking idiom. Unfortunately, it was not until this idiom was in fairly wide use that it became apparent that it is not a safe programming construct due to the current memory model. Work is underway to redefine areas of the memory model that are weak. However, even under the newly proposed memory model, double-checked locking will not work. The best solution to this problem is to accept synchronization or use a static field
.
- In his book Practical Java Programming Language Guide (Addison-Wesley, 2000), Peter Haggar covers a multitude of Java programming topics including an entire chapter on multithreading issues and programming techniques.
-
The Java Language Specification, Second Edition by Bill Joy, et. al. (Addison-Wesley, 2000) is the definitive technical reference for the Java programming language.
-
The Java Virtual Machine Specification, Second Edition by Tim Lindholm and Frank Yellin (Addison-Wesley, 1999) is the definitive document on Java compilers and runtime environments.
- Visit Bill Pugh's Java Memory Model Web site for a wealth of information on this important topic.
- For more information on
volatile
and 64-bit variables, see Peter Haggar's article "Does Java Guarantee Thread Safety?" in the June 2002 issue of Dr. Dobb's Journal .
-
JSR-133 deals with the revision to Java platform's memory model and thread specification.
- Java software consultant Brian Goetz examines when to use synchronization in "Threading lightly: Synchronization is not the enemy" (developerWorks, July 2001).
- In "Threading lightly: Sometimes it's best not to share" (developerWorks, October 2001), Brian Goetz examines
ThreadLocal
and offers tips for exploiting its power.
- In "Writing multithreaded Java applications" (developerWorks, February 2001), Alex Roetter introduces the Java Thread API, outlines issues involved in multithreading, and offers solutions to common problems.
- Find other Java technology resources on the developerWorks Java technology zone.
Peter Haggar is a Senior Software Engineer with IBM in Research Triangle Park, North Carolina, and the author of the book Practical Java Programming Language Guide published by Addison-Wesley. In addition, he has published numerous articles on Java programming. He has a broad range of programming experience, having worked on development tools, class libraries, and operating systems. At IBM, Peter works on emerging Internet technology and is currently focused on high-performance Web services. Peter is a frequent technical speaker on Java technology at numerous industry conferences. He has worked for IBM for more than 14 years and received a B.S. in Computer Science from Clarkson University. Contact Peter at haggar@us.ibm.com.
Total comments (10)Show: Most recent comments
All comments
Could this work? (see code below)
As I understand, the createInstance() method should not be elegible for inlining. Also it could be modified to include a local variable and perform other kinds of initialization apart from plain instantiation, always avoiding a reference to the "instance" static field.
Am I correct? Please, comment.
// Code.
public class Singleton
{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance()
{
if (instance == null)
synchronized (Singleton.class)
if (instance == null)
instance = createInstance();
return instance;
}
private static Singleton createInstance()
{
return new Singleton();
}
Posted by Taset on 10 March 2011
Hi MrKK,
Nice article. From your article, I got a question. please clarify.
'Out-of-order writes' can cause issue with any Synchronized blocks (that creates objects). It is not just with the Singletons. Right?
If this is the case, then single Synchronized blocks will never serve the purpose. We always need to go with nested Synchronized blocks. Is this correct statement? Please confirm?
Thanks,
Kalyan K Gondrala
Posted by KalyanKGondrala on 30 December 2010
Hi Mrkk, Can you please let me know the section which says that DCL is fixed. Thanks - Roy
Posted by MDABPM on 13 October 2010
http://jcp.org/en/jsr/detail?id=133
supposedly this is fixed in java 5
Posted by mrkk on 27 August 2010
发表评论
-
文本域显示行数算法
2021-03-10 22:46 280每行显示字符数: showCount 总共字符数:tot ... -
[初级容易犯错的地方]JAVA方法中的参数用final来修饰的效果(转)
2020-11-23 16:52 231今天顺便看到这个文章,转发一下,因是很多初级者容易犯错的地 ... -
Java批量解析微信dat文件,微信图片破解
2020-02-17 20:33 2035package com.chinada.dms.test.y ... -
Spring Framework 5.0 入门篇(转)
2019-04-25 10:00 01.为什么学习Spring? 随着对Java EE ... -
类中内部类中的方法访问外部类中变量的示例(转)
2018-10-06 21:23 436lass Day10_11 { public static ... -
java连接ssh到服务器执行命令(免密码)
2018-07-10 09:00 0今天在做不同服务器间,免密码执行curl 命令 Java ... -
于Aviator的规则引擎Demo(转)
2018-05-03 09:26 1816编写不易,转载请注明(http://shihlei.itey ... -
va网络爬虫经验分享(转)
2018-04-20 10:33 570最近三年很少写博客,虽然一直从事IT行业,但更多的是管理工作 ... -
高级Java开发人员最常访问的几个网站(转)
2018-04-19 14:30 298这是高级Java开发人员最常访问的几个网站。 这些网 ... -
趣味算法图解,文科生都看懂了(转)
2018-04-17 17:22 868编者按 IDEA 是由 Sándor ... -
Java Security:公钥私钥、数字签名、消息摘要是什么 (转)
2018-04-13 10:10 414https://www.cnblogs.com/f119436 ... -
一文了解十大 Java 开发者必备测试框架!(转)
2018-04-10 13:55 361想要提升自己的自动化测试技能吗?本文将介绍10个优秀的 Ja ... -
深入理解 Java 多线程核心知识:跳槽面试必备(转)
2018-04-02 13:43 320多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并 ... -
11大Java开源中文分词器的使用方法和分词效果对比(转)
2018-03-19 15:37 542原文出处: 杨尚川 本文的目标有两个: 1、学会使用1 ... -
远程debug代码(转)
2018-03-16 16:45 1012参考:http://blog.csdn.net/su ... -
微服务架构初探(转)
2018-03-16 16:39 630什么是微服务 ... -
你真的理解了MVC, MVP, MVVM吗?(转)
2018-03-15 15:26 539前言: 准备写这篇文章的时候 , 我自认为对MVC已经有深刻 ... -
JAR(Spring Boot)应用的后台运行配置(转)
2018-03-09 07:04 1106酱油一篇,整理一下关于Spring Boot后台运行的一些配 ... -
一位阿里架构师在2018年给每个程序员的小建议(转)
2018-03-01 15:54 567一位阿里架构师在2018年给每个程序员的小建议 1 ... -
Java 9 新特性,看这里就明白了(转)
2018-02-28 14:54 5581、Java9 新特性之---目 ...
相关推荐
对于Java开发者而言,熟悉并掌握各种设计模式是非常重要的,其中单态设计模式(通常称为单例模式)是一种非常实用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。 #### 二、单态设计模式的含义及...
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于...
Singleton设计模式是一种创建型设计模式,它的核心目标是确保在应用程序中只有一个类的实例,并提供一个全局访问点来获取这个唯一实例。这种模式在资源管理、缓存、日志记录、线程池等场景中广泛应用。 ### 单态...
下面是 Java 中 23 种设计模式的详细介绍: 创建型模式 1. 工厂方法模式(Factory Method Pattern) 工厂方法模式是一种创建型设计模式,它提供了一种创建对象的接口,允许客户端创建对象,而无需指定创建的类别...
单态模式(Singleton模式)是Java设计模式中的一种,它的主要目标是确保一个类在整个应用程序中只有一个实例存在。这种模式的应用场景广泛,特别是在需要全局共享的资源管理、配置中心、日志服务等场合非常常见。 ...
23种设计模式 创建模式 设计模式之Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证一个类只有一个实例,并提供一个访问它的全局访问点 设计模式之Factory(工厂方法和抽象工厂) 使用工厂模式就象使用 ...
设计模式之Singleton(单态) 结构模式: 设计模式之Facade(外观) 设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享...
单态模式(Singleton Pattern)是软件设计模式中的一种,它保证了类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如配置管理、线程池、缓存管理和日志记录等,因为它可以确保在整个系统中...
// 单态设计模式 class Singleton3 { // 私有构造函数防止外部直接实例化 private Singleton3() {} // 静态内部类持有Singleton3的唯一实例,保证线程安全 private static final Singleton3 s = new Singleton3...
单态设计模式(Singleton Pattern)是一种常见的软件设计模式,它的目标是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处包括资源管理的有效性、性能优化以及简化多线程环境下的同步控制。在Java中,...
单态模式(Singleton Pattern)是设计模式中的一种基础模式,主要用来确保一个类只有一个实例,并提供一个全局访问点。在软件工程中,当一个类只能有一个实例而且客户可以从一个众所周知的访问点访问它时,这样的...
Java 23 种设计模式 Java 23 种设计模式是 Java 中最常用的设计模式,总共可以分为三种:创建模式、结构模式和行为模式。创建模式包括 Factory(工厂模式)、Singleton(单态)、Builder(建造者模式)、Prototype...
单态模式(Singleton Pattern)是一种常用的软件设计模式,它的核心目标是确保一个类在整个应用程序中只有一个实例,并提供全局唯一的访问点。这种模式在资源管理、配置管理、对象协调等方面有广泛应用,例如创建...
在IT行业中,单态登录(Singleton Login)是一种常见的设计模式,尤其在Web应用程序开发中,用于确保用户在系统内只需登录一次,即可访问多个相互关联的子系统或应用,无需重复登录。本篇将深入探讨Java如何实现单态...
Java的23种设计模式是软件开发领域中一套广泛认可的模式,旨在提高代码的可复用性、可维护性和灵活性。设计模式按照其功能可以分为三大类:创建型模式、结构型模式和行为型模式。 1. 创建型模式 创建型模式涉及到...
下面是 23 种 Java 设计模式的总结: 创建型模式 创建型模式处理对象的创建机制,例如类的实例化过程,这些模式提供了一种方式来创建对象,而不是必须实例化一个类。 1.1.1 工厂方法模式(Factory Method Pattern...
Java的23种设计模式分为三大类:创建型、结构型和行为型。这些模式有助于提高代码的可读性、可维护性和可扩展性,是任何Java开发者必备的知识。 1. **创建型模式**: - **工厂方法(FactoryMethod)**:定义一个...
23种设计模式汇集 如果你还不了解设计模式是什么的话? 那就先看设计模式引言 ! 学习 GoF 设计模式的重要性 建筑和软件中模式之异同 A. 创建模式 设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例...
在软件工程领域,设计模式是为了解决特定问题而总结出来的经验性解决方案,它们提供了一种通用的语言,让设计师和开发者之间的沟通变得更为高效。Java设计模式是其中的佼佼者,它广泛应用在Java编程语言开发的项目中...
Factory(工厂模式)、Singleton(单态)、Builder(建造者模式)、Prototype(原型模式)、工厂方法模式。2、结构模式:Flyweight(共享模式)、Bridge(桥模式)、Decorator(装饰模式)、Composite(组合模式)、Adapter(适配器...