本文转载自:http://blog.csdn.net/doudou_bb_08/
1. 模式描述:大家想看就看把, 但是看的时候不能写哦.Read-Write Lock Pattern将读取与写入分开处理. 在读取数据之前,必须获取用来读取的锁定.而要写入的时候,则必须获取用来写入的锁定.因为读取的时候,实例的状态不会改变,所以,就算有多个线程在同时读取也没有关系.但,有人在读取的时候,不可做写入的操作.写入的时候,实例的状态就会改变,于是,当有一个线程在写入的时候,其他的线程不可以进行读取或写入.一般来说,进行共享互斥会使程序性能变差,但将写入的共享互斥与读取的共享互斥分开思考,就可以提升程序的性能.2. 参与者:2.1. Reader(读取者)参与者.2.2. Writer(写入者)参与者.2.3. SharedResource(共享资源)参与者.2.4. ReadWriteLock(读写用锁定)参与者.3. 示例程序:3.1 ShareResource类 - SharedResource(共享资源)参与者:
package com.quf.study.thread.readwritelock; import java.io.Serializable; /** */ /** * <strong>Title : ShareResource<br></strong> * <strong>Description : </strong>共享数据实体类.<br> * <strong>Create on : 2008-4-30<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人 修改日期 修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public final class ShareResource implements Serializable ... { /** *//** * <code>serialVersionUID</code>-注释 */ private static final long serialVersionUID = 235799050473308166L; /** *//** * <code>m_buf</code>-数据. */ private final char[] m_buf; /** *//** * <code>m_lock</code>-读写锁. */ private final ReadWriteLock m_lock = new ReadWriteLock(true); /** *//** * 构造函数 */ public ShareResource(int size) ...{ // TODO Auto-generated constructor stub this.m_buf = new char[size]; for ( int i = 0 ; i < this.m_buf.length ;i++ ) ...{ this.m_buf[i] = '*'; } } /** *//** * 读取数据. * <br> * 该方法中使用了before/after模式 * <pre> * before操作; * * try{ * * execute(); * * }finally{ * * after操作; * * } * </pre> * @return 数据数组. */ public char[] read() throws InterruptedException...{ //申请读取锁定. this.m_lock.readLock(); try ...{ return this.doRead(); } finally ...{ this.m_lock.readUnLock(); } } /** *//** * 写入数据. * @param data - 要写入的数据. */ public void write(char data) throws InterruptedException...{ //申请写入锁定. //this.m_lock.writeLock(); try ...{ this.m_lock.writeLock(); this.doWrite(data); } finally ...{ this.m_lock.writeUnLock(); } } /** *//** * 读取数据. * @return 数据集合. */ private char[] doRead()...{ char[] t_newBuf = new char[this.m_buf.length]; for ( int i = 0 ; i < this.m_buf.length ; i++ ) ...{ t_newBuf[i] = this.m_buf[i]; } this.doSlowly(); return t_newBuf; } /** *//** * 写入数据. * @param data - 写入的数据. */ private void doWrite(char data)...{ for ( int i = 0 ; i < this.m_buf.length ;i++ ) ...{ this.m_buf[i] = data; this.doSlowly(); } } /** *//** * 线程休眠. */ private void doSlowly()...{ try ...{ Thread.sleep(50); } catch (InterruptedException e) ...{ // TODO: handle exception } }} // END CLASS OF Data.3.2 ReadWriteLock类 - 读写锁:
package com.quf.study.thread.readwritelock; import java.io.Serializable; /** */ /** * <strong>Title : ReadWriteLock<br></strong> * <strong>Description : </strong>读写锁类.<br> * <pre> * 为了保护安全性,必须防止以下两种冲突: * 1. 读取和写入冲突. * 2. 写入和写入冲突. * * 为了达到以上的保护,可以获取读取锁定,写入锁定的条件有以下4种情况: * 1. 当线程想获取访问的锁定时........ * <1>已经有线程正在写入时,等待. * 理由: 不等待的话,会引起read-write conflict. * <2>已经有线程在进行读取时,不等代. * 理由: read-read不会造成conflict. * 2. 当线程想要获取写入用的锁定时: * <3>已经有线程在进行写入时,等待. * 理由: 不等待的话,会引起write-write conflict. * <4>已经有线程在进行读取时,等待. * 理由: 不等待的话, 会引起read-write conflict. * </pre> * <strong>Create on : 2008-4-30<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人 修改日期 修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public final class ReadWriteLock implements Serializable ... { /** *//** * <code>serialVersionUID</code>-注释 */ private static final long serialVersionUID = -6877946865095666037L; /** *//** * <code>m_readingReaders</code>-正在进行读取操作的线程数量. */ private int m_readingReaders; /** *//** * <code>m_waitingWriters</code>-正在等待写操作的线程数量. */ private int m_waitingWriters; /** *//** * <code>m_writingWriters</code>-正在进行写操作的线程数量. */ private int m_writingWriters; /** *//** * <code>m_preferWrite</code>-是否优先写操作标志.true - 优先写操作,false - 正常顺序. */ private boolean m_preferWrite; /** *//** * 构造函数 * @param preferWrite-是否优先写操作标志.true - 优先写操作,false - 正常顺序. */ public ReadWriteLock(boolean preferWrite) ...{ // TODO Auto-generated constructor stub this.m_preferWrite = preferWrite; } /** *//** * 获取读取锁. * @throws InterruptedException */ public synchronized void readLock() throws InterruptedException ...{ //如果正在写入的线程数>0 或者 (写优先 并且 等待写入的线程数 > 0 ) 则等待. if ( this.m_writingWriters > 0 || (this.m_preferWrite && this.m_waitingWriters > 0 ) ) ...{ wait(); } this.m_readingReaders++; } /** *//** * 释放读取锁. * @throws InterruptedException */ public synchronized void readUnLock() throws InterruptedException...{ this.m_readingReaders--; this.m_preferWrite = true; notifyAll(); } /** *//** * 获取写入锁. * @throws InterruptedException */ public synchronized void writeLock() throws InterruptedException...{ //正在等待写入的计数器+1. this.m_waitingWriters++; try ...{ //如果 ( 正在读取的线程数 > 0 或者 正在写入的线程数 > 0 ) 则等待. if ( this.m_readingReaders > 0 || this.m_writingWriters > 0 ) ...{ wait(); } } finally ...{ this.m_waitingWriters--; } this.m_writingWriters++; } /** *//** * 释放写入锁. * @throws InterruptedException */ public synchronized void writeUnLock() throws InterruptedException...{ this.m_writingWriters--; this.m_preferWrite = false; notifyAll(); } } // END CLASS OF ReadWriteLock.3.3 ReadDataThread - 读取数据的线程类:
package com.quf.study.thread.readwritelock; /** */ /** * <strong>Title : ReaderThread<br></strong> * <strong>Description : </strong>读取数据的线程.<br> * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人 修改日期 修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public final class ReadDataThread extends Thread ... { /** *//** * <code>m_data</code>-注释 */ private final ShareResource m_data; /** *//** * 构造函数 * @param data */ public ReadDataThread(ShareResource data) ...{ this.m_data = data; } /**//* (non-Javadoc) * @see java.lang.Thread#run() */ public void run()...{ try ...{ while( true ) ...{ char[] t_readBuf = this.m_data.read(); System.out.println(Thread.currentThread().getName()+" reads "+String.valueOf(t_readBuf) ); } } catch (InterruptedException e) ...{ // TODO: handle exception } }} // END CLASS OF ReadDataThread.3.4 WriteDataThread - 写入数据的线程类:
package com.quf.study.thread.readwritelock; import java.util.Random; /** */ /** * <strong>Title : WriteDataThread<br></strong> * <strong>Description : </strong>写数据的线程.<br> * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人 修改日期 修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public final class WriteDataThread extends Thread ... { /** *//** * <code>s_random</code>-注释 */ public static final Random s_random = new Random(); /** *//** * <code>m_data</code>-注释 */ private final ShareResource m_data; /** *//** * <code>m_filter</code>-注释 */ private final String m_filter; /** *//** * <code>m_index</code>-注释 */ private int m_index; /** *//** * 构造函数 * @param data * @param filter */ public WriteDataThread(ShareResource data,String filter)...{ this.m_data = data; this.m_filter = filter; } /**//* (non-Javadoc) * @see java.lang.Thread#run() */ public void run() ...{ try ...{ while ( true ) ...{ char t_data = this.nextChar(); this.m_data.write(t_data); Thread.sleep(s_random.nextInt(3000)); } } catch (InterruptedException ie) ...{ } } /** *//** * 获取下一个字符. * @return 下一个字符. */ private char nextChar() ...{ char t_c = this.m_filter.charAt(this.m_index); this.m_index++; if ( this.m_index >= this.m_filter.length() ) ...{ this.m_index = 0 ; } return t_c; }} // END CLASS OF WriteDataThread.3.5 ReadWriteLockTest - 测试类:
package com.quf.study.thread.readwritelock; /** */ /** * <strong>Title : ReadWriteLockTest<br></strong> * <strong>Description : </strong>读写锁测试类.<br> * <strong>Create on : 2008-5-4<br></strong> * <p> * <strong>Copyright (C) QUF Software Co.,Ltd.<br></strong> * <p> * @author renxin renxin777@126.com<br> * @version <strong>Java Thread Design Pattern Study</strong><br> * <br> * <strong>修改历史:</strong><br> * 修改人 修改日期 修改描述<br> * -------------------------------------------<br> * <br> * <br> */ public final class ReadWriteLockTest ... { public static void main(String[] args ) ...{ //创建数据对象. ShareResource t_data = new ShareResource(10); new ReadDataThread(t_data).start(); new ReadDataThread(t_data).start(); new ReadDataThread(t_data).start(); new ReadDataThread(t_data).start(); new ReadDataThread(t_data).start(); new ReadDataThread(t_data).start(); new WriteDataThread(t_data,"ABCDEFGHIJKLMNOPQRSTUVWXYZ").start(); new WriteDataThread(t_data,"abcdefghijklmnopqrstuvwxyz").start(); } } // END CLASS OF ReadWriteLockTest.4. 扩展思考方向:4.1 该模式利用同时读取而不会产生冲突的特性,提高了程序的性能.4.2 该模式适合读取操作比较繁重的情况.4.3 该模式适合读取比写入操作频繁时.4.4 锁定的意义:
使用synchronized,可以获取实例的锁定.Java程序的每个实例各有一个"锁定",同一个实 例的锁定无法由两个以上的线程所获取.这是制定在JAVA语言规格里,实现在Java执行环 境里的机制.故称为物理性的锁定.Java程序无法去改变这种锁定的行为.5. 相关知识:4.1 Before/After Pattern:前置处理(获取锁定)try{实际的操作.} finally {后续处理
(解除锁定)}
