诗剑书生的专栏

我在灌江口上住,花开花落,不知流年度.雁过空遗秋色暮,抚琴细听梧桐雨. 轻舞残虹漫展书,云卷云舒,思愫万千缕.安得婵娟与共处,长作识字耕田夫.                   诗剑书生 于灌江口.听潮居

用户操作
[即时聊天] [发私信] [加为好友]
诗剑书生ID:axman
109032次访问,排名816好友0人,关注者16
一个男人. 一个写程序男人. 一个写程序并从程序中寻找快乐的男人. 一个写程序并从程序中寻找快乐又把快乐传递给大家的男人.
一个书生. 一个寂寞的书生. 一个寂寞的梅香竹影下敲声写韵的书生. 一个寂寞的梅香竹影下敲声写韵晨钟暮鼓中逸气扬剑的书生.
那个男人是位书生。没有人知道他的姓名,居无定所,行无定踪,亦耕亦读,或渔或樵。
axman的文章
原创 88 篇
翻译 0 篇
转载 0 篇
评论 161 篇
axman的公告
最近评论
ZangXT:醍醐灌顶
matay:能不能把这个打包mms的工程源代码共享一下?万分感谢!
mataym@gmail.com
axman:不用说明什么,一切都如我预料的那样.
在整个奥运开幕式期间,我一边看电视,一边访问
http://www.cctvolympics.com/main.php?type=vod这个地址,其间访问一百多次,没有一次成功.大多数时候是前端缓存的squid在报refuse(111).有时以过几分钟的等待,能出来页面,但Flash缓冲的进度条到了99%就一直停止在那儿.
……
myvicc:写得不错,等写下文
chinagavin:我是先读三位正向输出,然后再读三位反向输出来最终达到想要的结果。
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 Java 多线程编程中的设计模式 开篇收藏

    新一篇: 多线程编程的设计模式 临界区模式(一) | 旧一篇: 多线程编程 深入理解JMM

     

    <放水开始>
    什么是模式?有太多的介绍模式的书,似乎用不着我再来给模式下一个定义.正如什么是道?
    除了老子有权解释,其他任何试图向别人解释什么是道的人,其实根本就不懂道!更别说什么
    初论,再论,三论,x论,末流之论也.你不论说明你还懂一些,如果你论,说明你根本就不懂道.
    因为老子已经说得非常清楚:道可道,非常道!

    那么我们是否已经陷入了不可知论?非也.不可道之道,是真正的大道.大道虽然无形,但每个人对它
    的感受是有形有,我们在向别人说明时其实说的是你"自己对道的感觉",无论你如何论道你的感觉都
    不代表真正的"道".

    因为每个人的感觉不同,所以尽管有很多人介绍过模式,我从中学习了很多我不知道的知识,但我有
    我的感受,我也有其它人不知道的知识,或者张狂一点说比某些人高明一些的知识,所以我要写我自
    己的模式系列.以我的观点而言:
    <放水暂停>

     
     模式就是在某种特定环境中,经常多次发生的问题的通用解决方案.

    环境,或说背景,用Java术语说是Context.
    问题里面还包含可以解决问题的外力条件(force),多个外力条件常常表现为"鱼与熊掌"的关系.

     尽管目前真正介绍模式的书并不多,但在可见的介绍模式的书中,可以看到多数就是一本
    模式词典.设计模式中真正的知识在于[模式语言].

     模式语言是模式的集合,集合的意思是集而合之,不是聚合.
     把多个相关的,相互作用的模式集而合之,并清楚地描述它们之间的关系.就是模式语言.

    模式是对某一个或某部分问题的通用解决方法.而模式语言是对某一领域中多个相关的问题集的解决
    方案的集成.这不仅仅是程序设计和软件开发过程的问题,任何领域中,能够描述出原则,主次,方法,
    技巧的抽象集合都是模式语言.

     如果你还要继续向下看,或者你还有兴趣看我的放水文章.那么请记住这句话:

     [学会模式和自如地应用模式进行设计是完全不同的两回事],keep it in your mind!

    <放水继续>
     记得在清华举行的中国软件业协会JAVA分成立大会上,我向Java程序员推荐过两本哲学的书.
    <<全息论>>,<<系统与层次>>.现在我再多加一本中科院哲学所刘长林先生的<<内经的哲学和中医学的方法>>

     宏观与微观:
     很多时候,我在与一些朋友讨论一些"细节"的内容时,总有些人问"讨论这种问题对解决软件
    企业的实际问题有何意义?",不客气地说,这些无知的话题决定了提问者本身就不可能有真正的解决
    "企业级应用问题"的能力.

     作为一个建筑设计师,他自己当然不会去干抹水泥,码砖头这样的活.但他要比这些码砖头,抹水泥的
    小工更清楚每块砖头的强度,年限,每种水泥的凝固时间,粘度等细节参数.否则你的设计再好也只
    能建一个豆腐渣工程.

     作为一个软件系统架构师,如果不懂你的coder在项目中使用的细节技术,重要组件,重要API实现
    你如何保证你的项目的性能和可靠性?难道真的靠默念口诀就能获得一种神奇的效果?

    有人说"一个人一生的时间的有限的,把太多的时候花在这些细节上,我就没有更多的时间掌握好些最实用的如structs,spring,hb等",那么我告诉你,如果你不了解最基础的东西,你学三个月structs,spring,hb,我只要一周会

    比你掌握更深入,即使Upload这样的小工具,明知道smartUpload的Bug巨多,不好用,有几个人能自动手写出来?当我第一次使用时我就花了40分钟自己写了一个公开在bea论坛上经几年大家的试用还未发现bug,这就是"微观"的重要性.

     "设计时脑子里只的模型,对象,实现时调试到汇编!".

     这是我一贯以求并一直坚持的架构原则.对于一个架构师而言,与程序设计相关的知识没有主要和
    次要之分,从单片机到汇编到到软件工程思想.都是你应该掌握的.听过撒贝宁讲背书的事,因为他老是不上课,
    所以复习时不知道哪里是老师划过的重点.好,那我把整本书作为重点背下来!

     如何应用模式和模式语言?在你掌握了模式与模式语言的情况下,有三种应用水平:
     一是在学会了很多模式后在设计时总是想用上一些模式为了显示我懂设计模式,如果这样你还不
    如一点不懂设计模式.Just in time(需要的时候才去做)!
     二是在遇到类似问题时能熟悉应用现有模式,这是绝对大多数如我这类中人之资水平能做的事.总之
    "不会过日看邻居"一般是不会错的.
     三是一种因为掌握了很多模式的基础上,经过不断实践在需要解决问题时没有现成的模式可用时自己
    抽象出设计模式.相信自己,你可以做到!

     所谓大师能做到举手投足之间都有惊世骇俗之举.嘻笑怒骂之间也能成黄钟大品之作.而我们常人,
    在平凡的生活中总会能悟出一点特别的东西,只不过不如大师那样来得容易.

     我把要放水的内容在首节放完,下面就一心一意讲我的设计模式知识.本系列绝不是模式词典.
    <放水结束>

     这篇文章算是开场,就不连着介绍第一个模式了.但和它相关的是比任何模式更重要的一篇文章.转
    贴过来,这才是模式的境界:(注意不是看懂它.而是能做到才是真正的设计模式境界)
     
     A C# Bedtime Story
    The following is an excerpt from Windows Forms 2.0 Programming, Chris Sells & Michael Weinhardt, Addison-Wesley, 2006. It's been updated from the original version for C# 2.0.

    Once upon a time, in a strange land south of here, there was a worker named Peter. He was a diligent worker who would readily accept requests from his boss. However, his boss was a mean, untrusting man who insisted on steady progress reports. Since Peter did not want his boss standing in his office looking over his shoulder, Peter promised to notify his boss whenever his work progressed. Peter implemented this promise by periodically calling his boss back via a typed reference like so:

    class Worker {
      Boss boss;
     
      public void Advise(Boss boss) {
        this.boss = boss;
      }
     
      public void DoWork() {
        Console.WriteLine("Worker: work started");
        if( this.boss != null ) this.boss.WorkStarted();
     
        Console.WriteLine("Worker: work progressing");
        if( this.boss != null ) this.boss.WorkProgressing();
     
        Console.WriteLine("Worker: work completed");
        if( this.boss != null ) {
          int grade = this.boss.WorkCompleted();
          Console.WriteLine("Worker grade= {0}", grade);
        }
      }
    }
     
    class Boss {
      public void WorkStarted() {
        // Boss doesn't care
      }
      public void WorkProgressing() {
        // Boss doesn't care
      }
      public int WorkCompleted() {
        Console.WriteLine("It's about time!");
        return 2; // out of 10
      }
    }
     
    class Universe {
      static void Main() {
        Worker peter = new Worker();
        Boss boss = new Boss();
        peter.Advise(boss);
        peter.DoWork();
     
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
      }
    }

    Interfaces
    Now Peter was a special person. Not only was he able to put up with his mean-spirited boss, but he also had a deep connection with the universe around him. So much so that he felt that the universe was interested in his progress. Unfortunately, there was no way for Peter to advise the Universe of his progress unless he added a special Advise method and special callbacks just for the Universe, in addition to keeping his boss informed. What Peter really wanted to do was to separate the list of potential notifications from the implementation of those notification methods. And so he decided to split the methods into an interface:

    interface IWorkerEvents {
      void WorkStarted();
      void WorkProgressing();
      int WorkCompleted();
    }
     
    class Worker {
      IWorkerEvents events;
     
      public void Advise(IWorkerEvents events) {
        this.events = events;
      }
     
      public void DoWork() {
        Console.WriteLine("Worker: work started");
        if( this.events != null ) this.events.WorkStarted();
     
        Console.WriteLine("Worker: work progressing");
        if( this.events != null ) this.events.WorkProgressing();
     
        Console.WriteLine("Worker: work completed");
        if( this.events!= null ) {
          int grade = this.events.WorkCompleted();
          Console.WriteLine("Worker grade= {0}", grade);
        }
      }
    }
     
    class Boss : IWorkerEvents {
      public void WorkStarted() {
        // Boss doesn't care
      }
      public void WorkProgressing() {
        // Boss doesn't care
      }
      public int WorkCompleted() {
        Console.WriteLine("It's about time!");
        return 3; // out of 10
      }
    }

    Delegates
    Unfortunately, Peter was so busy talking his boss into implementing this interface that he didn't get around to notifying the Universe, but he knew he would soon. At least he'd abstracted the reference of his boss far away from him so that others who implemented the IWorkerEvents interface could be notified of his work progress.

    Still, his boss complained bitterly. "Peter!" his boss fumed. "Why are you bothering to notify me when you start your work or when your work is progressing?!? I don't care about those events. Not only do you force me to implement those methods, but you're wasting valuable work time waiting for me to return from the event, which is further expanded when I am far away! Can't you figure out a way to stop bothering me?"

    And so, Peter decided that while interfaces were useful for many things, when it came to events, their granularity was not fine enough. He wished to be able to notify interested parties only of the events that matched their hearts' desires. So, he decided to break the methods out of the interface into separate delegate functions, each of which acted like a little tiny interface of one method each:

    delegate void WorkStarted();
    delegate void WorkProgressing();
    delegate int WorkCompleted();
     
    class Worker {
      public WorkStarted Started;
      public WorkProgressing Progressing;
      public WorkCompleted Completed;
     
      public void DoWork() {
        Console.WriteLine("Worker: work started");
        if( this.Started != null ) this.Started();
     
        Console.WriteLine("Worker: work progressing");
        if( this.Progressing != null ) this.Progressing();
     
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          int grade = this.Completed();
          Console.WriteLine("Worker grade= {0}", grade);
        }
      }
    }
     
    class Boss {
      public int WorkCompleted() {
        Console.WriteLine("It's about time!");
        return 4; // out of 10
      }
    }
     
    class Universe {
      static void Main() {
        Worker peter = new Worker();
        Boss boss = new Boss();
     
        // NOTE: We've replaced the Advise method with the assignment operation
        peter.Completed = new WorkCompleted(boss.WorkCompleted);
        peter.DoWork();
     
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
      }
    }

    And, because Peter was under so much pressure, he decided to advantage of the shorthand notation for assigning delegates provided by C# 2.0:

    class Universe {
      static void Main() {
        ...
        peter.Completed = boss.WorkCompleted;
        ...
      }
    }

    Static Listeners
    Delegates accomplished the goal of not bothering his boss with events that he didn't want, but still Peter had not managed to get the universe on his list of listeners. Since the universe is an all-encompassing entity, it didn't seem right to hook delegates to instance members (imagine how many resources multiple instances of the universe would need...). Instead, Peter need to hook delegates to static members, which delegates support fully:

    class Universe {
      static void WorkerStartedWork() {
        Console.WriteLine("Universe notices worker starting work");
      }
     
      static int WorkerCompletedWork() {
        Console.WriteLine("Universe pleased with worker's work");
        return 7;
      }
     
      static void Main() {
        Worker peter = new Worker();
        Boss boss = new Boss();
     
        peter.Completed = boss.WorkCompleted;
        peter.Started = WorkerStartedWork;
        peter.Completed = WorkerCompletedWork; // Oops!
        peter.DoWork();
     
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
      }
    }

    Events
    Unfortunately, the Universe being very busy and unaccustomed to paying attention to individuals, has managed to replace Peter's boss's delegate with its own. This is an unintended side effect of making the delegate fields public in Peter's Worker class. Likewise, if Peter's boss gets impatient, he can decide to fire Peter's delegates himself (which is just the kind of rude thing that Peter's boss was apt to do):

    // Peter's boss taking matters into his own hands
    if( peter.Completed != null ) peter.Completed();

    Peter wants to make sure that neither of these can happens. He realizes he needs to add registration and unregistration functions for each delegate so that listeners can add or remove themselves, but can't clear the entire list or fire Peter's events. Instead of implementing these functions himself, Peter uses the event keyword to make the C# compiler build these methods for him:

    class Worker {
      public event WorkStarted Started;
      public event WorkProgressing Progressing;
      public event WorkCompleted Completed;
      ...
    }

    Peter knows that the event keyword erects a property around a delegate, only allowing clients to add or remove themselves (using the += and -= operators in C#), forcing his boss and the universe to play nicely:

    class Universe {
      ...
      static void Main() {
        Worker peter = new Worker();
        Boss boss = new Boss();

        peter.Completed = boss.WorkCompleted; // ERR!
        peter.Completed += boss.WorkCompleted; // OK
        peter.Started += Universe.WorkerStartedWork; // OK
        peter.Completed += Universe.WorkerCompletedWork; // OK

        peter.DoWork();

        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
      }
    }

    Harvesting All Results
    At this point, Peter breathes a sigh of relief. He has managed to satisfy the requirements of all his listeners without having to be closely coupled with the specific implementations. However, he notices that while both his boss and the universe provide grades of his work that he's only receiving one of the grades. In the face of multiple listeners, he'd really like to harvest all of their results. So, he reaches into his delegate and pulls out the list of listeners so that he can call each of them manually:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
     
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            int grade = wc();
            Console.WriteLine("Worker grade= {0}", grade);
          }
        }
      }
    }
     
    public void DoWork() {
      ...
      Console.WriteLine("Worker: work completed");
      if( completed != null ) {
        foreach( WorkCompleted wc in completed.GetInvocationList() ) {
          int grade = wc();
          Console.WriteLine("Worker grade= " + grade);
        }
      }
    }

    Asynchronous Notification: Fire & Forget
    In the meantime, his boss and the universe have been distracted with other things, which meant that the time it takes them to grade Peter's work is greatly expanded:

    class Boss {
      public int WorkCompleted() {
        System.Threading.Thread.Sleep(5000);
        Console.WriteLine("Better...");
        return 4; // out of 10
      }
    }

    class Universe {
      ...
      static int WorkerCompletedWork() {
        System.Threading.Thread.Sleep(1000000);
        Console.WriteLine("Universe pleased with worker's work");
        return 7;
      }
      ...
    }

    Unfortunately, since Peter is notifying each listener one at a time, waiting for each to grade him, these notifications now take up quite a bit of his time when he should be working. So, he decides to forget the grade and just fire the event asynchronously:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            wc.BeginInvoke(null, null); // EndInvoke call required by .NET
          }
        }
      }
    }

    Asynchronous Notification: Polling
    The call to BeginInvoke allows Peter to notify the listeners while letting Peter get back to work immediately, letting the process thread pool invoke the delegate. Over time, however, Peter finds that he misses the feedback on his work. He knows that he does a good job and appreciates the praise of the universe as a whole (if not his boss specifically). Plus, hes afraid hes leaking .NET resources acquired by calling BeginInvoke without calling the corresponding EndInvoke method, so, he fires the event asynchronously, but polls periodically, looking for the grade to be available:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            IAsyncResult result = wc.BeginInvoke(null, null);
            while( !result.IsCompleted ) System.Threading.Thread.Sleep(1);
            int grade = wc.EndInvoke(result);
           Console.WriteLine("Worker grade= {0}", grade);
          }
        }
      }
    }

    Asynchronous Notification: Delegates
    Unfortunately, Peter is back to what he wanted his boss to avoid with him in the beginning, i.e. looking over the shoulder of the entity doing the work. So, he decides to employ his own delegate as a means of notification when the asynchronous work has completed, allowing him to get back to work immediately, but still be notified when his work has been graded:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            wc.BeginInvoke(this.WorkGraded, wc);
          }
        }
      }

      void WorkGraded(IAsyncResult result) {
        WorkCompleted wc = (WorkCompleted)result.AsyncState;
        int grade = wc.EndInvoke(result);
        Console.WriteLine("Worker grade= {0}" + grade);
      }
    }

    Anonymous Delegates
    At this point, Peter is using delegates to notify interested parties in the process of his work and using delegates to get notified when grades are available on the work hes completed. The delegates provided by his boss and the universe are provided by separate entities, so it makes sense that they are encapsulated in methods on those entities. However, in the case of the WorkGraded method, theres really no good reason for this to be a separate method except the syntactic requirements of C# 1.0. As of C# 2.0, Peter can drop the code required to handle the processing of his work grade into an anonymous delegate:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            wc.BeginInvoke(delegate(IAsyncResult result) {
              WorkCompleted wc2 = (WorkCompleted)result.AsyncState;
              int grade = wc2.EndInvoke(result);
              Console.WriteLine("Worker grade= {0}", grade);
            },
            wc);
          }
        }
      }
    }

    Here, instead of passing in the name of a method to call when his work has been graded, hes passing in the body of the method itself as designated with a different use of the delegate keyword to create a method with no name (and therefore anonymous). The body of the method is fundamentally the same in that Peter still passes the WorkCompleted delegate as a parameter to BeginInvoke and then pulls it out of AsyncState for use in extracting the result. However, one of the benefits of anonymous delegates that Peter knows is that he can make use of the variables in the surrounding context from within the anonymous delegate body, causing him to rewrite his code thusly:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            wc.BeginInvoke(delegate(IAsyncResult result) {
              // Use wc variable from surrounding context (ERR!)
              int grade = wc.EndInvoke(result);
              Console.WriteLine("Worker grade= {0}", grade);
            },
            null);
          }
        }
      }
    }

    This code compiles just fine, but when its run, it will cause the following exception to be thrown:

    System.InvalidOperationException:
      The IAsyncResult object provided does not match this delegate.
    The problem is that while the wc variable is allowed to be used in the anonymous delegate, its still being used by the for-each statement. As soon as the asynchronous invocation begins, the wc variable changes and the delegate used to start things (wc) no longer matches the async result passed as an argument to the anonymous delegate. Peter slaps his head and creates a hybrid solution:

    class Worker {
      ...
      public void DoWork() {
        ...
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            // Create an unchanging variable referencing the current delegate
            WorkCompleted wc2 = wc;
            wc.BeginInvoke(delegate(IAsyncResult result) {
              // Use wc2 variable from surrounding context
              int grade = wc2.EndInvoke(result);
              Console.WriteLine("Worker grade= {0}", grade);
            },
            null);
          }
        }
      }
    }
     
    public void DoWork() {
      ...
      Console.WriteLine("Worker: work completed");
      if( completed != null ) {
        foreach( WorkCompleted wc in completed.GetInvocationList() ) {
          wc.BeginInvoke(new AsyncCallback(WorkGraded), wc);
        }
      }
    }
     
    void WorkGraded(IAsyncResult res) {
      WorkCompleted wc = (WorkCompleted)res.AsyncState;
      int grade = wc.EndInvoke(res);
      Console.WriteLine("Worker grade= " + grade);
    }

    Happiness in the Universe
    Peter, his boss and the universe are finally satisfied. Peter's boss and the universe are allowed to be notified of the events that interest them, reducing the burden of implementation and the cost of unnecessary round-trips. Peter can notify them each, ignoring how long it takes them to return from their target methods, while still getting his results asynchronously and handling them using anonymous delegates, resulting in the following complete solution:

    delegate void WorkStarted();
    delegate void WorkProgressing();
    delegate int WorkCompleted();

    class Worker {
      public event WorkStarted Started;
      public event WorkProgressing Progressing;
      public event WorkCompleted Completed;
     
      public void DoWork() {
        Console.WriteLine("Worker: work started");
        if( this.Started != null )
          this.Started();
     
        Console.WriteLine("Worker: work progressing");
        if( this.Progressing != null )
          this.Progressing();
     
        Console.WriteLine("Worker: work completed");
        if( this.Completed != null ) {
          foreach( WorkCompleted wc in this.Completed.GetInvocationList() ) {
            WorkCompleted wc2 = wc;
            wc.BeginInvoke(delegate(IAsyncResult result) {
              int grade = wc2.EndInvoke(result);
              Console.WriteLine("Worker grade= {0}", grade);
            },
            null);
          }
        }
      }
    }

    class Boss {
      public int WorkCompleted() {
        System.Threading.Thread.Sleep(3000);
        Console.WriteLine("Better...");
        return 5; // out of 10
      }
    }

    class Universe {
      static void WorkerStartedWork() {
        Console.WriteLine("Universe notices worker starting work");
      }

      static int WorkerCompletedWork() {
        System.Threading.Thread.Sleep(4000);
        Console.WriteLine("Universe pleased with worker's work");
        return 7;
      }

      static void Main() {
        Worker peter = new Worker();
        Boss boss = new Boss();
        peter.Completed += boss.WorkCompleted;
        peter.Started += Universe.WorkerStartedWork;
        peter.Completed += Universe.WorkerCompletedWork;
        peter.DoWork();

        Console.WriteLine("Main: worker completed work");
      }
    }

    Peter knows that getting results asynchronously comes with issues, because as soon as he fires events asynchronously, the target methods are likely to be executed on another thread, as is Peter's notification of when the target method has completed. However, Peter is good friends with Mike, who is very familiar with threading issues and can provide guidance in that area.

    And they all lived happily every after.

    The end.
     

    发表于 @ 2006年08月23日 10:00:00|评论(loading...)|编辑

    新一篇: 多线程编程的设计模式 临界区模式(一) | 旧一篇: 多线程编程 深入理解JMM

    评论

    #agag 发表于2006-09-04 15:38:00  IP: 218.1.111.*
    标题是"Java 多线程编程中的设计模式",但是看了内容发现并不是java。
    #axman 发表于2006-09-05 10:24:00  IP: 210.82.61.*
    不知道你说的是下面转贴的那篇文章还是说我的整篇内容.
    如果说整篇内容这是我的习惯,在一个系列开始时来点"开栏语"这内的东西我想这没有什么错,就象序言不涉及具体内容一样.

    如果你是说下面转贴的那篇文章的话,那只好说是你不理解什么叫"模式".

    且不说c#与java是在模型上是最接近的.即使加其它语言,一种模式完全可以适用n多种具体语言.我转贴的这篇文章可以看出作者对于模式如此灵活的应用,其思想101%地可以移植到JAVA上.难道我非要把这个过程用java再重写一次来为我自己增光而不顾对作者的不敬?

    这也是我这里唯一引用的文章,我明确地说明是转贴的.这"开篇"中联系一些更高级的话题,超越于java和多线程之上模式,我想这应该没有任何不可理解的.
    #stone 发表于2006-09-08 14:55:00  IP: 219.239.110.*
    看了你在bea的中文网站上发布的多线程编程-基础篇,受益匪浅,不知道什么时候可以阅读到高级篇?
    :)

    同时把你的文章的地址放在这吧
    http://dev2dev.bea.com.cn/bbsdoc/20060831322.html
    #axman 发表于2006-09-12 10:30:00  IP: 210.82.61.*
    在本blog的go deep into java final中有详细的多线程系列文章
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © axman