﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-黑咖啡-文章分类-JAVA基础</title><link>http://www.blogjava.net/kyleYang/category/43249.html</link><description>孩儿立志出乡关，学不成名誓不还。
风华正茂乾坤地，人生无处不青山。
光阴如同流水去，珍惜时光最宝贵。
鹏程万里靠自己，飞黄腾达青少年。
</description><language>zh-cn</language><lastBuildDate>Wed, 23 Dec 2009 11:27:35 GMT</lastBuildDate><pubDate>Wed, 23 Dec 2009 11:27:35 GMT</pubDate><ttl>60</ttl><item><title>单例模式完全解析</title><link>http://www.blogjava.net/kyleYang/articles/307056.html</link><dc:creator>飞熊</dc:creator><author>飞熊</author><pubDate>Wed, 23 Dec 2009 08:34:00 GMT</pubDate><guid>http://www.blogjava.net/kyleYang/articles/307056.html</guid><wfw:comment>http://www.blogjava.net/kyleYang/comments/307056.html</wfw:comment><comments>http://www.blogjava.net/kyleYang/articles/307056.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kyleYang/comments/commentRss/307056.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kyleYang/services/trackbacks/307056.html</trackback:ping><description><![CDATA[本文将探讨单例模式的各种情况，并给出相应的建议。单例模式应该是设计模式中比较简单的一个，但是在多线程并发的环境下使用却是不那么简单了。<br />首先看最原始的单例模式。<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> Singleton {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> Singleton instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">;<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> Singleton() {<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> Singleton getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"> (instance </span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">            instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> Singleton();<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">        }<br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> instance;<br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">17</span> </div><br />显然这个写法在单线程环境下非常好，但是多线程会导致多个实例出现，这个大家都能理解。<br />最简单的改造方式是添加一个同步锁。<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> SynchronizedSingleton {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> SynchronizedSingleton instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">;<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> SynchronizedSingleton() {<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">synchronized</span><span style="COLOR: rgb(0,0,0)"> SynchronizedSingleton getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"> (instance </span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">            instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> SynchronizedSingleton();<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">        }<br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> instance;<br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">17</span> </div><br />显然上面的方法避免了并发的问题，但是由于我们只是在第一次构造对象的时候才需要同步，以后就不再需要同步，所以这里不可避免的有性能开销。于是将锁去掉采用静态的属性来解决同步锁的问题。<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> StaticSingleton {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> StaticSingleton instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> StaticSingleton();<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> StaticSingleton() {<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> StaticSingleton getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> instance;<br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">14</span> </div><br />上面的方法既没有锁又解决了性能问题，看起来已经满足需求了。但是追求“完美”的程序员想延时加载对象，希望在第一次获取的时候才构造对象，于是大家非常聪明的进行改造，也即非常出名的双重检查锁机制出来了。<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> DoubleLockSingleton {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> DoubleLockSingleton instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">;<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> DoubleLockSingleton() {<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> DoubleLockSingleton getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"> (instance </span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">            </span><span style="COLOR: rgb(0,0,255)">synchronized</span><span style="COLOR: rgb(0,0,0)"> (DoubleLockSingleton.</span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">                </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)"> (instance </span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">                    instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> DoubleLockSingleton();<br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">                }<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">            }<br /></span><span style="COLOR: rgb(0,128,128)">17</span> <span style="COLOR: rgb(0,0,0)">        }<br /></span><span style="COLOR: rgb(0,128,128)">18</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> instance;<br /></span><span style="COLOR: rgb(0,128,128)">19</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">20</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">21</span> </div><br />双重锁机制看起来非常巧妙的避免了上面的问题。但是真的是这样的吗？文章《<a href="http://www.ibm.com/developerworks/cn/java/j-dcl.html" target="_blank"><font color="#56b6e9">双重检查锁定及单例模式</font></a>》中谈到了非常多演变的双重锁机制带来的问题，包括比较难以理解的指令重排序机制等。总之就是双重检查锁机制仍然对导致错误问题而不是性能问题。<br />于是继续改造，某个牛人利用JVM的特性来解决上述问题，具体哪个牛人我忘记了，但是不是下面文章的作者。<br />（1）《<a href="http://www.ibm.com/developerworks/java/library/j-jtp03304/" target="_blank"><font color="#56b6e9">Java theory and practice: Fixing the Java Memory Model, Part 2</font></a>》<br />（2）《<a href="http://www.theserverside.com/discussions/thread.tss?thread_id=35349" target="_blank"><font color="#56b6e9">Initialize-On-Demand Holder Class and Singletons</font></a>》<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> HolderSingleton {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonHolder {<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> HolderSingleton instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> HolderSingleton();<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> HolderSingleton() {<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)">maybe throw an Exception when doing something </span><span style="COLOR: rgb(0,128,0)"><br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> HolderSingleton getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonHolder.instance;<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">17</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">18</span> </div><br /><br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"><br /></span></div><br />上述代码看起来解决了上面单例模式遇到的所有问题，而且实际上工作的很好，没有什么问题。但是却有一个致命的问题，如果第11行抛出了一个异常，也就是第一次构造函数失败将导致永远无法再次得到构建对象的机会。<br />使用下面的代码测试下。<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton;<br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonTest {<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonHolder {<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonTest instance </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonTest();<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">boolean</span><span style="COLOR: rgb(0,0,0)"> init </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">false</span><span style="COLOR: rgb(0,0,0)">;<br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">    <br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonTest() {<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)">maybe throw an Exception when doing something </span><span style="COLOR: rgb(0,128,0)"><br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,0)">!</span><span style="COLOR: rgb(0,0,0)">init) {<br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">            init</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,255)">true</span><span style="COLOR: rgb(0,0,0)">;<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">            </span><span style="COLOR: rgb(0,0,255)">throw</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> RuntimeException(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">fail</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">);<br /></span><span style="COLOR: rgb(0,128,128)">17</span> <span style="COLOR: rgb(0,0,0)">        }<br /></span><span style="COLOR: rgb(0,128,128)">18</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">19</span> <span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">20</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonTest getInstance() {<br /></span><span style="COLOR: rgb(0,128,128)">21</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> HolderSingletonHolder.instance;<br /></span><span style="COLOR: rgb(0,128,128)">22</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">23</span> <span style="COLOR: rgb(0,0,0)">    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> main(String[] args) {<br /></span><span style="COLOR: rgb(0,128,128)">24</span> <span style="COLOR: rgb(0,0,0)">        </span><span style="COLOR: rgb(0,0,255)">for</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> i</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;i</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">3</span><span style="COLOR: rgb(0,0,0)">;i</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">) {<br /></span><span style="COLOR: rgb(0,128,128)">25</span> <span style="COLOR: rgb(0,0,0)">            </span><span style="COLOR: rgb(0,0,255)">try</span><span style="COLOR: rgb(0,0,0)"> {<br /></span><span style="COLOR: rgb(0,128,128)">26</span> <span style="COLOR: rgb(0,0,0)">                System.out.println(HolderSingletonTest.getInstance());<br /></span><span style="COLOR: rgb(0,128,128)">27</span> <span style="COLOR: rgb(0,0,0)">            } </span><span style="COLOR: rgb(0,0,255)">catch</span><span style="COLOR: rgb(0,0,0)"> (Exception e) {<br /></span><span style="COLOR: rgb(0,128,128)">28</span> <span style="COLOR: rgb(0,0,0)">                System.err.println(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">one-&gt;</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">i);<br /></span><span style="COLOR: rgb(0,128,128)">29</span> <span style="COLOR: rgb(0,0,0)">                e.printStackTrace();<br /></span><span style="COLOR: rgb(0,128,128)">30</span> <span style="COLOR: rgb(0,0,0)">            }</span><span style="COLOR: rgb(0,0,255)">catch</span><span style="COLOR: rgb(0,0,0)">(ExceptionInInitializerError err) {<br /></span><span style="COLOR: rgb(0,128,128)">31</span> <span style="COLOR: rgb(0,0,0)">                System.err.println(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">two-&gt;</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">i);<br /></span><span style="COLOR: rgb(0,128,128)">32</span> <span style="COLOR: rgb(0,0,0)">                err.printStackTrace();<br /></span><span style="COLOR: rgb(0,128,128)">33</span> <span style="COLOR: rgb(0,0,0)">            }</span><span style="COLOR: rgb(0,0,255)">catch</span><span style="COLOR: rgb(0,0,0)">(Throwable t) {<br /></span><span style="COLOR: rgb(0,128,128)">34</span> <span style="COLOR: rgb(0,0,0)">                System.err.println(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">three-&gt;</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">i);<br /></span><span style="COLOR: rgb(0,128,128)">35</span> <span style="COLOR: rgb(0,0,0)">                t.printStackTrace();<br /></span><span style="COLOR: rgb(0,128,128)">36</span> <span style="COLOR: rgb(0,0,0)">            }<br /></span><span style="COLOR: rgb(0,128,128)">37</span> <span style="COLOR: rgb(0,0,0)">        }<br /></span><span style="COLOR: rgb(0,128,128)">38</span> <span style="COLOR: rgb(0,0,0)">    }<br /></span><span style="COLOR: rgb(0,128,128)">39</span> <span style="COLOR: rgb(0,0,0)">}<br /></span><span style="COLOR: rgb(0,128,128)">40</span> </div>很不幸将得到以下输出：<br /><div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="COLOR: rgb(0,128,128)"> 1</span> <span style="COLOR: rgb(0,0,0)">two</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)"> 2</span> <span style="COLOR: rgb(0,0,0)">java.lang.ExceptionInInitializerError<br /></span><span style="COLOR: rgb(0,128,128)"> 3</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">21</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)"> 4</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">26</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)"> 5</span> <span style="COLOR: rgb(0,0,0)">Caused by: java.lang.RuntimeException: fail<br /></span><span style="COLOR: rgb(0,128,128)"> 6</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">init</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)"> 7</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">init</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">12</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)"> 8</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder.</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">clinit</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">7</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)"> 9</span> <span style="COLOR: rgb(0,0,0)">    <img alt="" src="http://www.blogjava.net/images/dot.gif" /> </span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)"> more<br /></span><span style="COLOR: rgb(0,128,128)">10</span> <span style="COLOR: rgb(0,0,0)">three</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">11</span> <span style="COLOR: rgb(0,0,0)">java.lang.NoClassDefFoundError: Could not initialize </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder<br /></span><span style="COLOR: rgb(0,128,128)">12</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">21</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)">13</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">26</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)">14</span> <span style="COLOR: rgb(0,0,0)">three</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,128,128)">15</span> <span style="COLOR: rgb(0,0,0)">java.lang.NoClassDefFoundError: Could not initialize </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder<br /></span><span style="COLOR: rgb(0,128,128)">16</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">21</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)">17</span> <span style="COLOR: rgb(0,0,0)">    at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:</span><span style="COLOR: rgb(0,0,0)">26</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,128,128)">18</span> </div><br />很显然我们想着第一次加载失败第二次能够加载成功，非常不幸，JVM一旦加载某个类失败将认为此类的定义有问题，将来不再加载，这样就导致我们没有机会再加载。目前看起来没有办法避免此问题。如果要使用JVM的类加载特性就必须保证类加载一定正确，否则此问题将比并发和性能更严重。如果我们的类需要初始话那么就需要想其它办法避免在构造函数中完成。看起来像是又回到了老地方，难道不是么？<br /><br />总之，结论是目前没有一个十全十美的单例模式，而大多数情况下我们只需要满足我们的需求就行，没必有特意追求最“完美”解决方案。<br />原文[<span id="sample-permalink"><a href="http://www.imxylz.cn/p/177.html"><font color="#56b6e9">http://www.imxylz.cn/p/177.html</font></a></span>]<img src ="http://www.blogjava.net/kyleYang/aggbug/307056.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kyleYang/" target="_blank">飞熊</a> 2009-12-23 16:34 <a href="http://www.blogjava.net/kyleYang/articles/307056.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>