﻿<?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-勤加练习，必能得心应手！不期速成，日拱一卒 ！-随笔分类-线程-模式-设计</title><link>http://www.blogjava.net/ldwblog/category/44998.html</link><description>态度决定一切</description><language>zh-cn</language><lastBuildDate>Tue, 07 Jan 2020 10:49:50 GMT</lastBuildDate><pubDate>Tue, 07 Jan 2020 10:49:50 GMT</pubDate><ttl>60</ttl><item><title>个人公众号「Java爱好者社区」高质量原创文章持续输出，欢迎各位小主关注</title><link>http://www.blogjava.net/ldwblog/archive/2019/10/30/434887.html</link><dc:creator>David1228</dc:creator><author>David1228</author><pubDate>Wed, 30 Oct 2019 06:10:00 GMT</pubDate><guid>http://www.blogjava.net/ldwblog/archive/2019/10/30/434887.html</guid><wfw:comment>http://www.blogjava.net/ldwblog/comments/434887.html</wfw:comment><comments>http://www.blogjava.net/ldwblog/archive/2019/10/30/434887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldwblog/comments/commentRss/434887.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldwblog/services/trackbacks/434887.html</trackback:ping><description><![CDATA[blogjava网站与博客园合并了，对blogjava还是有感情的。<br />并且blogjava网站发布的文章是在博客园首页看不到的。<br />blogjava网站首页能看到，你可以点击标题进入可以看到图片二维码信息。<br /><br /><strong style="color: red; font-size: 14pt;">Java爱好者社区</strong><br />公众号内容简介：<br /><p><span style="background-color: yellow; color: red;">专注于分享Java后端相关技术、老司机实战干货，不限于JVM、并发、设计模式、性能优化、分布式&amp;微服务、云原生、大数据相关主题。</span><br style="color: red;" /><span style="background-color: yellow; color: red;">希望关注的你停下脚步，定有所收获。</span><br style="color: red;" /><br />以前的个人博客内容不好迁移，所以我打算根据自己的多年经验，不断整理输出有价值的内容。<br />目前公众号内容有关于<span style="background-color: yellow; color: red;">SpringCloud（微服务框架）、Skywalking（APM监控调用链）、JVM（GC分析、内存泄漏分析）、并发编程</span>相关原创实战文章已出炉。<br /><br />最近刚开始已经有不少小伙伴关注了，期待能有幸搜索到本博客的同学，可以扫码关注一下，不胜感激。<br />大家有任何技术、职场、面试上的问题都可以与我交流。<br /><br /><span style="background-color: yellow;"><strong>方式一：</strong></span><span style="color: red; background-color: yellow;"><strong>扫码以下公众号二维码：</strong></span><br /><img src="http://www.blogjava.net/images/blogjava_net/ldwblog/Java%E7%88%B1%E5%A5%BD%E8%80%85%E7%A4%BE%E5%8C%BA%E4%BA%8C%E7%BB%B4%E7%A0%81.png" border="0" alt="" /><br /><br />方式二：<span style="color: red;">在微信上直接搜索：&nbsp;</span><span style="color: red; background-color: yellow;">javatech_cbo</span><br /><br />感谢各位小伙伴的支持，后续会在该公众号上输出大量的有价值的实战干货 ，期待与你一同进步与成长。<br /></p><img src ="http://www.blogjava.net/ldwblog/aggbug/434887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldwblog/" target="_blank">David1228</a> 2019-10-30 14:10 <a href="http://www.blogjava.net/ldwblog/archive/2019/10/30/434887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单工厂模式与抽象工厂模式</title><link>http://www.blogjava.net/ldwblog/archive/2013/07/04/401215.html</link><dc:creator>David1228</dc:creator><author>David1228</author><pubDate>Thu, 04 Jul 2013 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/ldwblog/archive/2013/07/04/401215.html</guid><wfw:comment>http://www.blogjava.net/ldwblog/comments/401215.html</wfw:comment><comments>http://www.blogjava.net/ldwblog/archive/2013/07/04/401215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldwblog/comments/commentRss/401215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldwblog/services/trackbacks/401215.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文转载自：http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html场景问题　　举个生活中常见的例子&#8212;&#8212;组装电脑，我们在组装电脑的时候，通常需要选择一系列的配件，比如CPU、硬盘、内存、主板、电源、机箱等。为讨论使用简单点，只考虑选择CPU和主板的问题。　　事实上，在选择CPU的时候，面临一系列的...&nbsp;&nbsp;<a href='http://www.blogjava.net/ldwblog/archive/2013/07/04/401215.html'>阅读全文</a><img src ="http://www.blogjava.net/ldwblog/aggbug/401215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldwblog/" target="_blank">David1228</a> 2013-07-04 17:07 <a href="http://www.blogjava.net/ldwblog/archive/2013/07/04/401215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）定时且周期性的任务研究I--Timer ---- 任务研究II--ScheduledThreadPoolExecutor</title><link>http://www.blogjava.net/ldwblog/archive/2013/03/18/396615.html</link><dc:creator>David1228</dc:creator><author>David1228</author><pubDate>Mon, 18 Mar 2013 10:58:00 GMT</pubDate><guid>http://www.blogjava.net/ldwblog/archive/2013/03/18/396615.html</guid><wfw:comment>http://www.blogjava.net/ldwblog/comments/396615.html</wfw:comment><comments>http://www.blogjava.net/ldwblog/archive/2013/03/18/396615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldwblog/comments/commentRss/396615.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldwblog/services/trackbacks/396615.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: jdk并发部分，如果英文理解有点小难，可以参考http://www.yiibai.com/java6/java/util/concurrent/package-summary.html本篇转自：http://victorzhzh.iteye.com/blog/1011635很多时候我们希望任务可以定时的周期性的执行，在最初的JAVA工具类库中，通过Timer可以实现定时的周期性的需求，但是有一定的...&nbsp;&nbsp;<a href='http://www.blogjava.net/ldwblog/archive/2013/03/18/396615.html'>阅读全文</a><img src ="http://www.blogjava.net/ldwblog/aggbug/396615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldwblog/" target="_blank">David1228</a> 2013-03-18 18:58 <a href="http://www.blogjava.net/ldwblog/archive/2013/03/18/396615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Composite模式</title><link>http://www.blogjava.net/ldwblog/archive/2012/10/12/389470.html</link><dc:creator>David1228</dc:creator><author>David1228</author><pubDate>Fri, 12 Oct 2012 08:20:00 GMT</pubDate><guid>http://www.blogjava.net/ldwblog/archive/2012/10/12/389470.html</guid><wfw:comment>http://www.blogjava.net/ldwblog/comments/389470.html</wfw:comment><comments>http://www.blogjava.net/ldwblog/archive/2012/10/12/389470.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldwblog/comments/commentRss/389470.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldwblog/services/trackbacks/389470.html</trackback:ping><description><![CDATA[<small style="font-family: serif; line-height: normal; background-color: #ffffff; ">假设您今天要开发一个动画编辑程式，动画由影格（Frame）组成，数个影格组合为动画清单，动画清单也可以由其它已完成的动画清单组成，也可以在动画清单与清单之间加入个别影格。无论是影格或动画清单都可以播放，而动画清单负责的就是组合影格或动画清单，所以可以这么设计：<br /><br /><br /><img alt="" src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/Composite-1.jpg" style="width: 593px; height: 307px; " /><br /><br /></small><small style="font-family: serif; line-height: normal; background-color: #ffffff; ">对于Frame而言，Playlist是一个容器，然而Playlist也实作Playable，所以它也可以播放，您可以进一步地将Playlist组合至另一个Playlist中，以形成更长的播放清单。以Java实现的话。<br /></small><small style="font-family: serif; line-height: normal; background-color: #ffffff; "><small>以Java實現的話。<br /></small><pre style="color: #333333; border: 1px solid #777777; background-color: #eeeeee; margin: 3px 25px; padding: 0px 10px; font-size: small; line-height: 17px; width: auto; font-family: 'Courier New', Courier, monospace; ">import java.util.*;<br /><br />interface Playable {<br />    void play();<br />}<br /><br />class Frame implements Playable {<br />    private String image;<br />    Frame(String image) {<br />        this.image = image;<br />    }<br />    public void play() {<br />        System.out.println("播放 " + image);<br />    }<br />}<br /><br />class Playlist implements Playable {<br />    private List&lt;Playable&gt; list = new ArrayList&lt;Playable&gt;();<br />    public void add(Playable playable) {<br />        list.add(playable);<br />    }<br />    public void play() {<br />        for(Playable playable : list) {<br />            playable.play();<br />        }<br />    }<br />}<br /><br />public class Main {<br />    public static void main(String[] args) {<br />        Frame logo = new Frame("片頭 LOGO");<br />        <br />        Playlist playlist1 = new Playlist();<br />        playlist1.add(new Frame("Duke 左揮手"));<br />        playlist1.add(new Frame("Duke 右揮手"));<br />        <br />        Playlist playlist2 = new Playlist();<br />        playlist2.add(new Frame("Duke 走左腳"));<br />        playlist2.add(new Frame("Duke 走右腳"));<br />        <br />        Playlist all = new Playlist();<br />        all.add(logo);<br />        all.add(playlist1);<br />        all.add(playlist2);<br />        <br />        all.play();<br />    }<br />}</pre><small></small><small><br />以Python實現的話：<br /></small><pre style="color: #333333; border: 1px solid #777777; background-color: #eeeeee; margin: 3px 25px; padding: 0px 10px; font-size: small; line-height: 17px; width: auto; font-family: 'Courier New', Courier, monospace; ">class Frame:<br />    def __init__(self, image):<br />        self.image = image<br />    def play(self):<br />        print("播放 " + self.image)<br /><br />class Playlist:<br />    def __init__(self):<br />        self.list = []<br />    def add(self, playable):<br />        self.list.append(playable);<br />    def play(self):<br />        for playable in self.list:<br />            playable.play()<br />            <br />logo = Frame("片頭 LOGO")<br />        <br />playlist1 = Playlist()<br />playlist1.add(Frame("Duke 左揮手"))<br />playlist1.add(Frame("Duke 右揮手"))<br />        <br />playlist2 = Playlist()<br />playlist2.add(Frame("Duke 走左腳"))<br />playlist2.add(Frame("Duke 走右腳"))<br />        <br />all = Playlist()<br />all.add(logo)<br />all.add(playlist1)<br />all.add(playlist2)<br /><br /></pre><span style="background-color: #eeeeee; color: #333333; font-family: 'Courier New', Courier, monospace; font-size: small; line-height: 17px; ">all.play();</span>以UML来表示Composite模式的结构：<br /><img alt="" src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/Composite-2.jpg" style="width: 556px; height: 329px; " /><br /><br /></small><small style="font-family: serif; line-height: normal; background-color: #ffffff; "><br />具有层次性或组合性的物件可以使用Composite模式，像是电路元件、视窗元件等，使用Composite模式可以大大减低这些元件设计的复杂度，以Java标准API中AWT视窗元件为例，</small><small style="font-family: serif; line-height: normal; background-color: #ffffff; ">Component上有个paint()方法，可以进行元件的绘制，</small><small style="font-family: serif; line-height: normal; background-color: #ffffff; ">Container可以容纳Component（如Button、Label等），而Container继承Component，所以Container也可以容纳Container，这也是Composite模式的实际例子：<br /><img alt="" src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/Composite-3.jpg" style="width: 627px; height: 237px; " /></small>&nbsp;<br /><br />from ：&nbsp;<a href="http://caterpillar.onlyfun.net/Gossip/index.html">http://caterpillar.onlyfun.net/Gossip/index.html</a>&nbsp;<br /><br /><br /><br /><img src ="http://www.blogjava.net/ldwblog/aggbug/389470.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldwblog/" target="_blank">David1228</a> 2012-10-12 16:20 <a href="http://www.blogjava.net/ldwblog/archive/2012/10/12/389470.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程中单例模式</title><link>http://www.blogjava.net/ldwblog/archive/2010/05/14/320977.html</link><dc:creator>David1228</dc:creator><author>David1228</author><pubDate>Fri, 14 May 2010 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/ldwblog/archive/2010/05/14/320977.html</guid><wfw:comment>http://www.blogjava.net/ldwblog/comments/320977.html</wfw:comment><comments>http://www.blogjava.net/ldwblog/archive/2010/05/14/320977.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldwblog/comments/commentRss/320977.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldwblog/services/trackbacks/320977.html</trackback:ping><description><![CDATA[<p>Abstract</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在开发中，如果某个实例的创建需要消耗很多系统资源，那么我们通常会使用惰性加载机制，也就是说只有当使用到这个实例的时候才会创建这个实例，这个好处在单例模式中得到了广泛应用。这个机制在single-threaded环境下的实现非常简单，然而在multi-threaded环境下却存在隐患。本文重点介绍惰性加载机制以及其在多线程环境下的使用方法。（作者numberzero，参考IBM文章《Double-checked locking and the Singleton pattern》，欢迎转载与讨论）</p>
<p>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单例模式的惰性加载<br />
通常当我们设计一个单例类的时候，会在类的内部构造这个类（通过构造函数，或者在定义处直接创建），并对外提供一个static getInstance方法提供获取该单例对象的途径。例如： </p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20Singleton%20%20%20%20%20%20%0A%7B%20%20%20%20%20%20%0A%20%20%20%20private%20static%20Singleton%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%0A%20%20%20%20private%20Singleton()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%E2%80%A6%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%20%20%20%20public%20static%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20return%20instance%3B%20%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%7D%20%20%20%20%20%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; class&nbsp; Singleton&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp;&nbsp; static&nbsp; Singleton instance =&nbsp; new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp; Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public&nbsp;&nbsp; static&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
public class Singleton&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static Singleton instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样的代码缺点是：第一次加载类的时候会连带着创建Singleton实例，这样的结果与我们所期望的不同，因为创建实例的时候可能并不是我们需要这个实例的时候。同时如果这个Singleton实例的创建非常消耗系统资源，而应用始终都没有使用Singleton实例，那么创建Singleton消耗的系统资源就被白白浪费了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了避免这种情况，我们通常使用惰性加载的机制，也就是在使用的时候才去创建。以上代码的惰性加载代码如下：</p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20Singleton%7B%20%20%20%20%20%20%0A%20%20%20%20private%20static%20Singleton%20instance%20%3D%20null%3B%20%20%20%20%20%20%0A%20%20%20%20private%20Singleton()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%E2%80%A6%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%20%20%20%20public%20static%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20if%20(instance%20%3D%3D%20null)%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20instance%3B%20%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%7D%20%20%20%20%20%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; class&nbsp; Singleton{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp;&nbsp; static&nbsp; Singleton instance =&nbsp; null ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp; Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public&nbsp;&nbsp; static&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (instance ==&nbsp; null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
public class Singleton{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static Singleton instance = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，当我们第一次调用Singleton.getInstance()的时候，这个单例才被创建，而以后再次调用的时候仅仅返回这个单例就可以了。</p>
<p>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 惰性加载在多线程中的问题<br />
先将惰性加载的代码提取出来：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20static%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20if%20(instance%20%3D%3D%20null)%20%20%20%20%20%20%0A%20%20%20%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%20%0A%20%20%20%20return%20instance%3B%20%20%20%20%20%20%20%0A%7D%20%20%20%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; static&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if&nbsp; (instance ==&nbsp; null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; instance = new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return&nbsp; instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
public static Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是如果两个线程A和B同时执行了该方法，然后以如下方式执行：</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A进入if判断，此时foo为null，因此进入if内</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B进入if判断，此时A还没有创建foo，因此foo也为null，因此B也进入if内</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A创建了一个Foo并返回</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B也创建了一个Foo并返回</p>
<p>此时问题出现了，我们的单例被创建了两次，而这并不是我们所期望的。</p>
<p>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 各种解决方案及其存在的问题<br />
3.1&nbsp;&nbsp;&nbsp;&nbsp; 使用Class锁机制<br />
以上问题最直观的解决办法就是给getInstance方法加上一个synchronize前缀，这样每次只允许一个现成调用getInstance方法：</p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20static%20synchronized%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20if%20(instance%20%3D%3D%20null)%20%20%20%20%20%20%0A%20%20%20%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%20%0A%20%20%20%20return%20instance%3B%20%20%20%20%20%20%20%0A%7D%20%20%20%20%20%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; static&nbsp;&nbsp; synchronized&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if&nbsp; (instance ==&nbsp; null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; instance = new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return&nbsp; instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
public static synchronized Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 这种解决办法的确可以防止错误的出现，但是它却很影响性能：每次调用getInstance方法的时候都必须获得Singleton的锁，而实际上，当单例实例被创建以后，其后的请求没有必要再使用互斥机制了</p>
<p>3.2&nbsp;&nbsp;&nbsp;&nbsp; double-checked locking<br />
曾经有人为了解决以上问题，提出了double-checked locking的解决方案</p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20static%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20if%20(instance%20%3D%3D%20null)%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20synchronized(instance)%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if(instance%20%3D%3D%20null)%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%0A%20%20%20%20return%20instance%3B%20%20%20%20%20%20%20%0A%7D" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; static&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if&nbsp; (instance ==&nbsp; null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (instance){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (instance ==&nbsp; null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return&nbsp; instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public static Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(instance){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 让我们来看一下这个代码是如何工作的：首先当一个线程发出请求后，会先检查instance是否为null，如果不是则直接返回其内容，这样避免了进入 synchronized块所需要花费的资源。其次，即使第2节提到的情况发生了，两个线程同时进入了第一个if判断，那么他们也必须按照顺序执行 synchronized块中的代码，第一个进入代码块的线程会创建一个新的Singleton实例，而后续的线程则因为无法通过if判断，而不会创建多余的实例。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上述描述似乎已经解决了我们面临的所有问题，但实际上，从JVM的角度讲，这些代码仍然可能发生错误。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于JVM而言，它执行的是一个个Java指令。在Java指令中创建对象和赋值操作是分开进行的，也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序，也就是说有可能JVM会为新的Singleton实例分配空间，然后直接赋值给instance成员，然后再去初始化这个Singleton实例。这样就使出错成为了可能，我们仍然以A、B两个线程为例：</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A、B线程同时进入了第一个if判断</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A首先进入synchronized块，由于instance为null，所以它执行instance = new Singleton();</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于JVM内部的优化机制，JVM先画出了一些分配给Singleton实例的空白内存，并赋值给instance成员（注意此时JVM没有开始初始化这个实例），然后A离开了synchronized块。</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B进入synchronized块，由于instance此时不是null，因此它马上离开了synchronized块并将结果返回给调用该方法的程序。</p>
<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此时B线程打算使用Singleton实例，却发现它没有被初始化，于是错误发生了。</p>
<p>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过内部类实现多线程环境中的单例模式<br />
为了实现慢加载，并且不希望每次调用getInstance时都必须互斥执行，最好并且最方便的解决办法如下：</p>
<p>Java代码 &lt; type="application/x-shockwave-flash" width="14" height="15" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" src="http://xupo.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20Singleton%7B%20%20%20%20%20%20%0A%20%20%20%20private%20Singleton()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%E2%80%A6%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%20%20%20%20private%20static%20class%20SingletonContainer%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20private%20static%20Singleton%20instance%20%3D%20new%20Singleton()%3B%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%20%20%20%20public%20static%20Singleton%20getInstance()%7B%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20return%20SingletonContainer.instance%3B%20%20%20%20%20%20%0A%20%20%20%20%7D%20%20%20%20%20%20%0A%7D%20%20%20%20%20%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"&gt; <br />
public&nbsp;&nbsp; class&nbsp; Singleton{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp; Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp;&nbsp; static&nbsp;&nbsp; class&nbsp; SingletonContainer{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private&nbsp;&nbsp; static&nbsp; Singleton instance =&nbsp; new&nbsp; Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public&nbsp;&nbsp; static&nbsp; Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; SingletonContainer.instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
public class Singleton{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Singleton(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static class SingletonContainer{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static Singleton instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static Singleton getInstance(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SingletonContainer.instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM内部的机制能够保证当一个类被加载的时候，这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候，JVM能够帮我们保证instance只被创建一次，并且会保证把赋值给instance的内存初始化完毕，这样我们就不用担心3.2中的问题。此外该方法也只会在第一次调用的时候使用互斥机制，这样就解决了3.1中的低效问题。最后instance是在第一次加载SingletonContainer类时被创建的，而 SingletonContainer类则在调用getInstance方法的时候才会被加载，因此也实现了惰性加载。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/fancyerII/archive/2010/03/15/5382349.aspx</p>
 <img src ="http://www.blogjava.net/ldwblog/aggbug/320977.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldwblog/" target="_blank">David1228</a> 2010-05-14 14:17 <a href="http://www.blogjava.net/ldwblog/archive/2010/05/14/320977.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>