日历
«  2018 4  »
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
最新评论
网站统计
  • 建站时间: 2010/03/29
  • 日记:4147 篇
  • 照片:45 张
  • 话题:14 篇
  • 评论:1108 篇
  • 注册用户:14
  • 今日访问:436
  • 本周访问:14619
  • 本月访问:102432
  • 全部访问:5840263

lock  多线程UML

2010/08/11  作者:耀耀   心情: sunny  星期三 (21:54)

(三) 线程设计模式

什么是模式呢?Martin Flower先生这样描述:一个模式,就是在实际的上下文中,并且在其他上下文中也会有用的想法。

这边的线程设计模式大部分参考自林信良先生的《设计模式》,还有一些网路的文章,这些都是前辈们在使用线程时候的经验,非常值得我们借鉴。还有就是林信良先生的设计模式非常通俗易懂,是入门级选手的最佳选择。关于线程的模式应该还有别的,只是我这边现在只能总结这么多了,能力有限。这边用大量的UML来描述这些模式,但是由于我的UML学的不好,而且工具用的不怎么熟,画的图应该会有些问题,当做草图来看就好了。

1.         Single Threaded Execution

这个模式在Java里说的话有点多余,但是这边还是先拿这个开胃一下。很明显,从字面的意思,就是说同一时刻只有一个线程在执行,Java里用synchronized这个关键字来实现这个模式。确实多余 L!看看UML吧!其实用这个图来描述有点不好。其实应该用别的图来描述会比较好!比如协作图。

2.         Guarded Suspension

网上有一个比较好的描述方式:要等我准备好噢!

这里我们假设一种情况:一个服务器用一个缓冲区来保存来自客户端的请求,服务器端从缓冲区取得请求,如果缓冲区没有请求,服务器端线程等待,直到被通知有请求了,而客户端负责发送请求。

很显然,我们需要对缓冲区进行保护,使得同一时刻只能有一个服务器线程在取得request,也只能同一时刻有一个客户端线程写入服务。

UML描述如下:

具体实现可以参看代码。

但是,这个模式有一点点瑕疵,那就是缓冲区没有限制,对于有的情况就不会合适,比如说您的缓冲区所能占用的空间受到限制。下面的Producer Consumer Pattern应该会有所帮助。

3.         Producer Consumer

Producer Consumer跟上面的Guarded Suspension很像,唯一的区别在于缓冲区,Guarded Suspension模式的缓冲区没有限制,所以,他们适用的场合也就不一样了,很显然,这个考虑应该基于内存是否允许。Producer Consumer的缓冲区就像一个盒子,如果装满了,就不能再装东西,而等待有人拿走一些,让后才能继续放东西,这是个形象的描述。可以参考下面的UML,然后具体可以参看源码。

4.         Worker Thread

Worker Thread与上面的Producer-consumer模式的区别在于Producer-consumer只是专注于生产与消费,至于如何消费则不管理。其实Worker Thread模式是Producer-consumerCommand模式的结合。这边简单描述一下Command patternUML就和衣很清晰的描述Command pattern

这个模式在我们的很多MVC框架中几乎都会用到,以后我也想写一个关于Web应用的总结,会提到具体的应用。其实Command pattern模式的核心就是针对接口编程,然后存储命令,根据客户短的请求取得相应的命令,然后执行,这个跟我们的Web请求实在是太像了,其实Struts就是这样做的,容器相当于Client,然后控制器Servlet相当于InvokerAction相当于ICommand,那么Receiver相当于封装在Action中的对象了,比如Request等等。

上面描述过Command pattern之后,我们回到Worker模式。

这边看看workerUML

从图中可以看到,CommandBuffer这个缓冲区不仅仅能够存储命令,而且可以控制消费者WorkerThread。这就是Worker模式。下面的Sequence应该会更加明确的描述这个模式,具体可以参看代码。

5.         Thread-Per-Message

Thread-Per-Message模式是一个比较常用的模式了,如果我们有一个程序需要打开一个很大的文件,打开这个文件需要很长的时间,那么我们就可以设计让一个线程来一行一行的读入文件,而不是一次性的全部打开,这样从外部看起来就不会有停顿的感觉。这个模式Future模式一起学习。

6.         Read-Write-Lock

考虑这样一种情况:有一个文件,有很多线程对他进行读写,当有线程在读的时候,不允许写,这样是为了保证文件的一致性。当然可以很多线程一起读,这个没有问题。如果有线程在写,其他线程不允许读写。如果要比较好的处理这种情况,我们可以考虑使用Read-Write-Lock模式。

这个模式可以如下描述:

其实这个模式的关键在于锁实现,这里有个简单的实现如下:

public class Lock {

       private volatile int readingReaders = 0;

 

       @SuppressWarnings("unused")

       private volatile int writingWriters = 0;

 

       @SuppressWarnings("unused")

       private volatile int waitingWriters = 0;

 

       public synchronized void lockRead() {

 

              try {

                     while (writingWriters > 0 || waitingWriters > 0) {

                            wait();

                     }

              } catch (InterruptedException e) {

                     // null

              }

 

              readingReaders++;

       }

 

       public synchronized void unlockRead() {

              readingReaders--;

              notifyAll();

       }

 

       public synchronized void lockWrite() {

 

              waitingWriters++;

              try {

                     while (writingWriters > 0 || readingReaders > 0) {

                            wait();

                     }

              } catch (InterruptedException e) {

                     // null

              } finally {

                     waitingWriters--;

              }

 

              writingWriters++;

       }

 

       public synchronized void unlockWrite() {

              writingWriters--;

              notifyAll();

       }

}

其实在锁里还可以添加优先级之类的控制。

关键字: 多线程  UML 
引用地址: http://zdyc.net/html/trackback.do?id=80&type=1 (复制地址)
设计总结 | 评论(1000) | 阅读(109487) | Trackback(0) |