﻿<?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天空 任我翱翔-随笔分类-Design Patterns</title><link>http://www.blogjava.net/persister/category/26173.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 17 Sep 2010 10:14:55 GMT</lastBuildDate><pubDate>Fri, 17 Sep 2010 10:14:55 GMT</pubDate><ttl>60</ttl><item><title>多线程设计模式总结</title><link>http://www.blogjava.net/persister/archive/2010/01/31/311388.html</link><dc:creator>persister</dc:creator><author>persister</author><pubDate>Sun, 31 Jan 2010 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/persister/archive/2010/01/31/311388.html</guid><wfw:comment>http://www.blogjava.net/persister/comments/311388.html</wfw:comment><comments>http://www.blogjava.net/persister/archive/2010/01/31/311388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/persister/comments/commentRss/311388.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/persister/services/trackbacks/311388.html</trackback:ping><description><![CDATA[Java多线程设计模式，帮助多线程功能提高质量，降低学习成本。主要的Pattern如下：<br />
1.Single Threaded Execution Pattern 多个线程共享一个实例，这样的话，多个线程都<br />
&nbsp; 擅自改动实例的状态，实例会丧失安全性。这种情况可以通过Java的关键词synchronized来解决。如多个人<br />
&nbsp; 通过一个gate时，只能一个个通过，那么可以如下的方式：<br />
&nbsp; public synchronized void pass(String name){<br />
&nbsp;&nbsp; &nbsp;this.name = name;<br />
&nbsp; }<br />
&nbsp; synchronized方法的性能比普通的方法低，所以降低减少使用。<br />
&nbsp; JDK中很多方法是synchronized，可以安全使用，很多为了性能是没有同步。为了提高性能可以考虑使用&nbsp; Immutable Pattern<br />
2.Immutable Pattern 多个线程共享一个实例，但是实例的状态不会改变，可以提供throughput，但必须保证<br />
&nbsp; 不变形（实例的状态不会改变）。需要使用private，final等来支持。<br />
3.Guarded Suspension Pattern 多个线程共享一个实例，这样的话，多个线程都<br />
&nbsp; 擅自改动实例的状态，实例会丧失安全性。当实例的状态不恰当时，就要求线程等待到合适的状态，以&#8220;警戒条&nbsp;&nbsp; 件&#8221;来表示实例的&#8220;适当的状态&#8221;。如果警戒条件一直不成立，线程会永远等待下去，会使程序丧失生命性。Java&nbsp;&nbsp; 中用while循环来测试警戒条件，使用wait方法让线程等待，并使用notify/notifyAll通知警戒条件的改变。<br />
检&nbsp;&nbsp; 验、修改警戒条件是，会使用Single Threaded Execution Pattern。Pattern的例子如下：<br />
&nbsp; public class RequestQueue{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private final LinkedList queue = new LinkedList();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized Request getRequest(){<br />
&nbsp;&nbsp; &nbsp;while(queue.size() &lt;= 0){&nbsp;&nbsp; //警戒条件<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;wait();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException e){}<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;return (Request)queue.removeFirst();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void putRequest(Request request){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;queue.addLast(request);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;notifyAll();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp; }<br />
<br />
<br />
&nbsp; 以上使用Queue的客户端和服务器代码里面非常干净，没有多线程的东西，代码复用性很好。<br />
&nbsp; 当警戒条件不成立时想要马上退出，就使用Balking Pattern<br />
4.Balking Pattern 一直等待安全的时机，会使程序的响应性降低。Java语言中，检验警戒条件时要使用if语句<br />
&nbsp; ，当要balk时，可使用return退出方法，或者throw抛出异常。<br />
&nbsp; public class Data {<br />
&nbsp;&nbsp;&nbsp; private String filename;&nbsp;&nbsp;&nbsp; //修改是的名字<br />
&nbsp;&nbsp;&nbsp; private String content;&nbsp;&nbsp;&nbsp;&nbsp; // 资料的内容<br />
&nbsp;&nbsp;&nbsp; private boolean changed;&nbsp;&nbsp;&nbsp; //修改后的内容还没存储的话，值为true<br />
<br />
&nbsp;&nbsp;&nbsp; public Data(String filename, String content) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.filename = filename;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.content = content;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.changed = true;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; // 修改资料内容<br />
&nbsp;&nbsp;&nbsp; public synchronized void change(String newContent) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content = newContent;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; changed = true;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp; // 若有资料修改，就存储到挡安里<br />
&nbsp;&nbsp;&nbsp; public synchronized void save() throws IOException {&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!changed) {&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " balks");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return; //没有就退出&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSave();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; changed = false;&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;&nbsp;&nbsp;&nbsp;&nbsp;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp; // 实际资料储存到挡案里用的方法<br />
&nbsp;&nbsp;&nbsp; private void doSave() throws IOException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " calls doSave, content = " + content);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Writer writer = new FileWriter(filename);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.write(content);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.close();<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
5.Producer-Consumer Pattern 当Producer参与者与Consumer参与者处理的速度不同时，速度慢的会扯速度快的<br />
&nbsp; 后腿，而降低程序的throughput。解决的办法就是在两者之间，加上中继用的Channel参与者。并让Channel<br />
&nbsp; 参与者存放多条数据，这样就可以缓冲Producer和Consumer之间处理速度的差异。这个模式使用了Guarded <br />
&nbsp; Suspension Pattern。<br />
<br />
&nbsp; public class Table {<br />
&nbsp;&nbsp;&nbsp; private final String[] buffer;<br />
&nbsp;&nbsp;&nbsp; private int tail;&nbsp; /下一个放put的地方 <br />
&nbsp;&nbsp;&nbsp; private int head;&nbsp; //下一个放的take地方<br />
&nbsp;&nbsp;&nbsp; private int count; // buffer内的蛋糕数<br />
&nbsp;&nbsp;&nbsp; public Table(int count) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.buffer = new String[count];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.head = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.tail = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.count = 0;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; // 放置蛋糕<br />
&nbsp;&nbsp;&nbsp; public synchronized void put(String cake) throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " puts " + cake);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (count &gt;= buffer.length) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[tail] = cake;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tail = (tail + 1) % buffer.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; // 取得蛋糕<br />
&nbsp;&nbsp;&nbsp; public synchronized String take() throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (count &lt;= 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String cake = buffer[head];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; head = (head + 1) % buffer.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count--;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " takes " + cake);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cake;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
6.Read-Write Lock Pattern 多个线程共享一个实例，如进程之间不进行共享胡扯，会丧失安全性。<br />
&nbsp; 但使用Single Threaded Execution Pattern会使程序throughput降低。解决的方法就是将控制reader参与者的&nbsp;&nbsp;&nbsp; 锁定与控制writer参与者的锁定分开，加入ReadWriteLock参与者，以提供两种不同的锁定。<br />
&nbsp;<br />
&nbsp;public final class ReadWriteLock {<br />
&nbsp;&nbsp;&nbsp; private int readingReaders = 0; // (A)...实际正在读取的执行绪数量<br />
&nbsp;&nbsp;&nbsp; private int waitingWriters = 0; // (B)...正在等待写入的执行绪数量<br />
&nbsp;&nbsp;&nbsp; private int writingWriters = 0; // (C)...实际正在写入的执行绪数量<br />
&nbsp;&nbsp;&nbsp; private boolean preferWriter = true; // 写入优先的话，值为true<br />
<br />
&nbsp;&nbsp;&nbsp; public synchronized void readLock() throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (writingWriters &gt; 0 || (preferWriter &amp;&amp; waitingWriters &gt; 0)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readingReaders++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; (A)实际正在读取的线程数量加1<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public synchronized void readUnlock() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readingReaders--;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; (A)实际正在读取的线程数量减1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preferWriter = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public synchronized void writeLock() throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; waitingWriters++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (B)正在等待写入的线程数量加1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (readingReaders &gt; 0 || writingWriters &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; waitingWriters--;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (B)正在等待写入的线程数量减1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writingWriters++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; (C)实际正在写入的线程数量加1<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public synchronized void writeUnlock() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writingWriters--;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (C)实际正在写入的线程数量减<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preferWriter = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; public class Data {<br />
&nbsp;&nbsp;&nbsp; private final char[] buffer;<br />
&nbsp;&nbsp;&nbsp; private final ReadWriteLock lock = new ReadWriteLock();<br />
&nbsp;&nbsp;&nbsp; public Data(int size) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.buffer = new char[size];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; buffer.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i] = '*';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public char[] read() throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.readLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return doRead();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.readUnlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void write(char c) throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.writeLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doWrite(c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.writeUnlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private char[] doRead() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char[] newbuf = new char[buffer.length];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; buffer.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newbuf[i] = buffer[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slowly();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return newbuf;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private void doWrite(char c) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; buffer.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i] = c;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slowly();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private void slowly() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(50);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
7.Thread-Per-Message Pattern&nbsp; 在方法的属性处理完成之前，控制权不会从Host参与者退出。如果方法的处理<br />
&nbsp; 属性很话费时间，程序的响应性能会降低。解决的方式就在Host的参与者里，启动新的线程，并且将该方法应&nbsp;&nbsp;&nbsp; 该进行的工作交给这个心的线程，这样Client参与者的线程可以继续执行下一个操作，这样做，不用更改&nbsp;&nbsp;&nbsp; Client参与者的程序代码，并能提高程序的响应性。想节省启动线程所花费的时间，可以使用Worker Thread&nbsp;&nbsp;&nbsp; Pattern。<br />
&nbsp; public class Host {<br />
&nbsp;&nbsp;&nbsp; private final Helper helper = new Helper();<br />
&nbsp;&nbsp;&nbsp; public void request(final int count, final char c) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("&nbsp;&nbsp;&nbsp; request(" + count + ", " + c + ") BEGIN");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Thread() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; helper.handle(count, c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("&nbsp;&nbsp;&nbsp; request(" + count + ", " + c + ") END");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
8.Worker Thread Pattern 如果方法的处理属性很花时间，程序的响应性会降低。为了提供响应性，而启动新<br />
&nbsp; 的线程来处理方法时，启动线程所花的时间又会降低throughput。另外当送出的请求太多时，会启动<br />
&nbsp; 过多的线程，这会使承载量变差。<br />
&nbsp; public class Channel {<br />
&nbsp;&nbsp;&nbsp; private static final int MAX_REQUEST = 100;<br />
&nbsp;&nbsp;&nbsp; private final Request[] requestQueue;<br />
&nbsp;&nbsp;&nbsp; private int tail;&nbsp; // 下一个putRequest的地方<br />
&nbsp;&nbsp;&nbsp; private int head;&nbsp; // 下一个takeRequest的地方<br />
&nbsp;&nbsp;&nbsp; private int count; // Request的数量<br />
<br />
&nbsp;&nbsp;&nbsp; private final WorkerThread[] threadPool;<br />
<br />
&nbsp;&nbsp;&nbsp; public Channel(int threads) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.requestQueue = new Request[MAX_REQUEST];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.head = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.tail = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.count = 0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threadPool = new WorkerThread[threads];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; threadPool.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threadPool[i] = new WorkerThread("Worker-" + i, this);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void startWorkers() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; threadPool.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threadPool[i].start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public synchronized void putRequest(Request request) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (count &gt;= requestQueue.length) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; requestQueue[tail] = request;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tail = (tail + 1) % requestQueue.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public synchronized Request takeRequest() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (count &lt;= 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Request request = requestQueue[head];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; head = (head + 1) % requestQueue.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count--;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return request;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
9.Future Pattern 当Client会将工作委托给其他线程，而Client参与者希望得到处理的结果。将工作委托给<br />
&nbsp; 别人时，如果又等待执行结果，会使响应性降低。<br />
&nbsp; public class FutureData implements Data {<br />
&nbsp;&nbsp;&nbsp; private RealData realdata = null;<br />
&nbsp;&nbsp;&nbsp; private boolean ready = false;<br />
&nbsp;&nbsp;&nbsp; public synchronized void setRealData(RealData realdata) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ready) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;&nbsp;&nbsp;&nbsp;&nbsp; // balk<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.realdata = realdata;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ready = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyAll();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public synchronized String getContent() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (!ready) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return realdata.getContent();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
<br />
附多线程程序的评价标准<br />
1、安全性——不损坏对象 对象损坏是指对象的状态不符合设计师的原意，通常是获取对象的状态值并非预期值。<br />
2、生存性——进行必要的处理 也许不是现在，但是一定会进行必要的处理，如果程序安全了，但是有些必要的处理得不到操作，那么这个多线程程序也是不合格的。<br />
3、复用性——可再利用类 写多线程程序，如果能够将多线程的共享和互斥结构隐藏在类里面，这就是一个高度可复印的程序。<br />
4、性能——能快速大量处理 主要表现在吞吐量（Throughput）即一定时间内能完成的处理量，能完成的处理量越多，表示数据吞吐量越大；容量（Capacity）指可同时处理的数量；响应性（Responsiveness）指从发出请求到收到响应的时间，时间越短，响应性越高。<br />
5、伸缩性（Scalability）等<br />
<br />
前两个是必要条件，后面几个是程序质量的描述<br />
 <img src ="http://www.blogjava.net/persister/aggbug/311388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/persister/" target="_blank">persister</a> 2010-01-31 15:26 <a href="http://www.blogjava.net/persister/archive/2010/01/31/311388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多线程设计模式:wait/notify机制</title><link>http://www.blogjava.net/persister/archive/2009/12/03/304620.html</link><dc:creator>persister</dc:creator><author>persister</author><pubDate>Thu, 03 Dec 2009 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/persister/archive/2009/12/03/304620.html</guid><wfw:comment>http://www.blogjava.net/persister/comments/304620.html</wfw:comment><comments>http://www.blogjava.net/persister/archive/2009/12/03/304620.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/persister/comments/commentRss/304620.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/persister/services/trackbacks/304620.html</trackback:ping><description><![CDATA[通常，多线程之间需要协调工作。例如，浏览器的一个显示图片的线程displayThread想要执行显示图片的任务，必须等待下载线程
downloadThread将该图片下载完毕。<br />
如果图片还没有下载完，displayThread能暂停，当downloadThread完成了任务
后，再通知displayThread&#8220;图片准备完毕，能显示了&#8221;，这时，displayThread继续执行。　　<br />
以上逻辑简单的说就是：如果条件不满足，则等待。<br />
当条件满足时，等待该条件的线程将被唤醒。<br />
在Java中，这个机制的实现依赖于wait/notify。等待机制和锁机制是密切关联的。<br />
例如：　　<br />
<br />
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<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>&nbsp;<span style="color: rgb(0, 0, 255);">synchronized</span><span style="color: rgb(0, 0, 0);">(obj)<br />
</span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);">{　　<br />
</span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">condition)<br />
</span><span style="color: rgb(0, 128, 128);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">{<br />
</span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 0, 0);">　　obj.wait();　　<br />
</span><span style="color: rgb(0, 128, 128);">6</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 128, 128);">7</span>&nbsp;<span style="color: rgb(0, 0, 0);">}　　<br />
</span><span style="color: rgb(0, 128, 128);">8</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;obj.doSomething();　　<br />
</span><span style="color: rgb(0, 128, 128);">9</span>&nbsp;<span style="color: rgb(0, 0, 0);">}　</span></div>
当线程A获得了obj锁后，发现条件condition不满足，无法继续下一处理，于是线程A就wait()。　　在另一线程B中，如果B更改了某些条件，使得线程A的condition条件满足了，就能唤醒线程A：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<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>&nbsp;<span style="color: rgb(0, 0, 255);">synchronized</span><span style="color: rgb(0, 0, 0);">(obj)<br />
</span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);">{　　<br />
</span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;condition&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</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);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;obj.notify();　　<br />
</span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 0, 0);">}　</span></div>
<br />
<br />
需要注意的概念是：　　<br />
# 调用obj的wait(), notify()方法前，必须获得obj锁，也就是必须写在synchronized(obj) {...} 代码段内。　　<br />
<br />
# 调用obj.wait()后，线程A就释放了obj的锁，否则线程B无法获得obj锁，也就无法在synchronized(obj) {...} 代码段内唤醒A。　　<br />
<br />
# 当obj.wait()方法返回后，线程A需要再次获得obj锁，才能继续执行。　　<br />
# 如果A1,A2,A3都在obj.wait()，则B调用obj.notify()只能唤醒A1,A2,A3中的一个（具体哪一个由JVM决定）。　　<br />
# obj.notifyAll()则能全部唤醒A1,A2,A3，不过要继续执行obj.wait()的下一条语句，必须获得obj锁，因此，A1,A2,A3只有一个有机会获得锁继续执行，例如A1，其余的需要等待A1释放obj锁之后才能继续执行。　　<br />
# 当B调用obj.notify/notifyAll的时候，B正持有obj锁，因此，A1,A2,A3虽被唤醒，不过仍无法获得obj锁。直到B退出synchronized块，释放obj锁后，A1,A2,A3中的一个才有机会获得锁继续执行。
<img src ="http://www.blogjava.net/persister/aggbug/304620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/persister/" target="_blank">persister</a> 2009-12-03 14:45 <a href="http://www.blogjava.net/persister/archive/2009/12/03/304620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visitor设计模式的理解</title><link>http://www.blogjava.net/persister/archive/2007/07/31/133534.html</link><dc:creator>persister</dc:creator><author>persister</author><pubDate>Tue, 31 Jul 2007 03:32:00 GMT</pubDate><guid>http://www.blogjava.net/persister/archive/2007/07/31/133534.html</guid><wfw:comment>http://www.blogjava.net/persister/comments/133534.html</wfw:comment><comments>http://www.blogjava.net/persister/archive/2007/07/31/133534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/persister/comments/commentRss/133534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/persister/services/trackbacks/133534.html</trackback:ping><description><![CDATA[Visitor模式，在不修改已有程序结构的前提下，通过添加额外的&#8220;访问者&#8221;来完成对已有代码功能的提升。<br />
Visitor模式包括以下几个元素：<br />
<br />
1) 访问者接口（Visitor）：声明一个访问接口，定义visit接口，有几个元素就定义几个接口方法。接口方法的参数标识了具体访问元素角色，也就是说参数是一个具体类。这个地方也是Visitor的不足，<br />
<br />
2) 具体访问者（Concrete Visitor）：实现Visitor接口
<br />
<br />
3) 元素接口（Element）：定义一个accept方法，它以访问者接口为参数，这里不是具体的访问者，即不知道具体的访问者。<br />
<br />
4) 具体元素（Concrete Element）：实现元素（Element）接口中accept方法，控制访问的流程。<br />
<br />
5) 对象结构（Object Structure）：这是使用Visitor模式必须的角色。它要具备以下特征：能枚举它的元素；可以提供一个高层的接口允许访问者访问它的元素；可以是一个集合，如一个列表或一个无序集合。<br />
<br />
类图如下：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/persister/9du0ok8rj791.jpg" width="555" height="344" /><br />
<br />
具体代码：<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Visitor<br />
{<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitCollection(Collection&nbsp;collection);<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitString(String&nbsp;string);<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitFloat(Float&nbsp;</span><span style="color: #0000ff;">float</span><span style="color: #000000;">);<br />
}</span></div>
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ConcreteVisitor1&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Visitor<br />
{<br />
&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">在本方法中，我们实现了对Collection的元素的成功访问</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">　　&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitCollection(Collection&nbsp;collection)&nbsp;{<br />
&nbsp;　　&nbsp;Iterator&nbsp;iterator&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;collection.iterator()<br />
&nbsp;　　&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(iterator.hasNext())&nbsp;{<br />
&nbsp;　　&nbsp;　　&nbsp;Object&nbsp;o&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;iterator.next();<br />
&nbsp;　　&nbsp;　　&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(o&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;Visitable)<br />
&nbsp;　　&nbsp;　　&nbsp;　　&nbsp;((Visitable)o).accept(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
&nbsp;　　&nbsp;}<br />
<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitString(String&nbsp;string)&nbsp;{<br />
&nbsp;　　&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">'</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">string</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">'</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;}<br />
<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitFloat(Float&nbsp;</span><span style="color: #0000ff;">float</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;　　&nbsp;System.out.println(</span><span style="color: #0000ff;">float</span><span style="color: #000000;">.toString()</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">f</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;}<br />
} <br />
</span></div>
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Visitable<br />
{<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;accept(Visitor&nbsp;visitor);<br />
}&nbsp;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;StringElement&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Visitable<br />
{<br />
&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;value;<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ConcreteElement(String&nbsp;string)&nbsp;{<br />
&nbsp;　　&nbsp;value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;string;<br />
&nbsp;}<br />
&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">定义accept的具体内容&nbsp;这里是很简单的一句调用</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">　　&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;accept(Visitor&nbsp;visitor)&nbsp;{<br />
&nbsp;　　&nbsp;visitor.visitString(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
&nbsp;}<br />
}<br />
<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;FloatElement&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Visitable<br />
{<br />
&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Float&nbsp;value;<br />
&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ConcreteElement(Float&nbsp;f)&nbsp;{<br />
&nbsp;　　&nbsp;value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;f;<br />
&nbsp;}<br />
&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">定义accept的具体内容&nbsp;这里是很简单的一句调用</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">　　&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;accept(Visitor&nbsp;visitor)&nbsp;{<br />
&nbsp;　　&nbsp;visitor.visitFloat(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
&nbsp;}<br />
}</span></div>
<br />
总结：<br />
1、元素接口和元素类都是依赖Visitor接口，而不是具体实现类，很好的实现了解耦。如果有一个新的元素欢迎Visitor参观，只需要实现Visitable接口，并实现accept方法即可，都不牵涉具体的Visitor。<br />
<br />
2、Visitor接口则不然，它依赖具体的元素，也就是说如果元素的类型发生变化如增加一个元素类型，那么Visitor接口和具体实现类都必须大改，这个是Visitor模式严重的缺陷。<br />
<br />
3、Visitor模式名副其实，好比旅行社、游客和景点的关系。旅行社就是Visitor接口，这次路线都需要参观哪些景点通常是固定的（接口固定，如果要改变行程，通常很麻烦）；游客就这些景点，旅行社给你安排两个小时,你想自己怎么玩都行；景点则以不变应万变。这个比如也许有些不恰当，不过有助于理解这个模式。<br />
<br />
<img src ="http://www.blogjava.net/persister/aggbug/133534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/persister/" target="_blank">persister</a> 2007-07-31 11:32 <a href="http://www.blogjava.net/persister/archive/2007/07/31/133534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>