スレッドデザインパターン - Read-Write Lock -
6章の「Read-Writre Lock」をReadWriteLockインターフェイスを使ってみた。ここで注意したいのが、ReentrantReadWriteLockの均等性ポリシーをfair(コンストラクタの第一引数をtrue)にしておかないと、Readerスレッドの数が多いので、いつまでもWriterスレッドがロックを取得できなくなってしまう。
Main.java
package dp.chap06; public class Main { public static void main(String[] args) { Data data = new Data(10); new ReaderThread(data).start(); new ReaderThread(data).start(); new ReaderThread(data).start(); new ReaderThread(data).start(); new ReaderThread(data).start(); new ReaderThread(data).start(); new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXWZ").start(); new WriterThread(data, "abcdefghijklmnopqrstuvwxwz").start(); new WriterThread(data, "1234567890").start(); new WriterThread(data, "!\"#$%&'()-~|").start(); } }
ReaderThread.java
package dp.chap06; public class ReaderThread extends Thread { private final Data data_; public ReaderThread(Data data) { data_ = data; } public void run() { // try { while(true) { char[] readbuf = data_.read(); System.out.println(getName() + " reads " + String.valueOf(readbuf)); } // }catch(InterruptedException ie) { // } } }
WriterThread
package dp.chap06; import java.util.*; public class WriterThread extends Thread { private static final Random random_ = new Random(); private final Data data_; private final String filter_; private int index_ = 0; public WriterThread(Data data, String filter) { data_ = data; filter_ = filter; } public void run() { try { while(true) { char c = nextchar(); data_.write(c); sleep(random_.nextInt(3000)); } }catch(InterruptedException ie) { } } private char nextchar() { char c = filter_.charAt(index_++); if( index_ == filter_.length() ) index_ = 0; return c; } }
Data.java
package dp.chap06; import java.util.concurrent.locks.*;; public class Data { private final char[] buffer_; private final ReadWriteLock lock_ = new ReentrantReadWriteLock(true); public Data(int size) { buffer_ = new char[size]; for(int i=0; i<buffer_.length; ++i) buffer_[i] = '*'; } public char[] read() { lock_.readLock().lock(); try { return doRead(); }finally { lock_.readLock().unlock(); } } public void write(char c) { lock_.writeLock().lock(); try { doWrite(c); }finally { lock_.writeLock().unlock(); } } private char[] doRead() { char[] newbuf = new char[buffer_.length]; for(int i=0; i<buffer_.length; ++i) newbuf[i] = buffer_[i]; slowly(); return newbuf; } private void doWrite(char c) { for(int i=0; i<buffer_.length; ++i) { buffer_[i] = c; slowly(); } } private void slowly() { try { Thread.sleep(50); } catch(InterruptedException ie) {} } }
実行結果↓
Thread-0 reads ********** Thread-1 reads ********** Thread-2 reads ********** Thread-3 reads ********** Thread-4 reads ********** Thread-5 reads ********** Thread-0 reads !!!!!!!!!! Thread-1 reads !!!!!!!!!! Thread-2 reads !!!!!!!!!! Thread-3 reads !!!!!!!!!! Thread-4 reads !!!!!!!!!! Thread-5 reads !!!!!!!!!! Thread-0 reads BBBBBBBBBB Thread-1 reads BBBBBBBBBB Thread-2 reads BBBBBBBBBB Thread-3 reads BBBBBBBBBB Thread-4 reads BBBBBBBBBB Thread-5 reads BBBBBBBBBB Thread-0 reads 2222222222 Thread-1 reads 2222222222 (略) Thread-2 reads """""""""" Thread-0 reads """""""""" Thread-1 reads 3333333333 Thread-5 reads 3333333333 Thread-3 reads 3333333333 Thread-4 reads 3333333333 Thread-2 reads 3333333333 Thread-0 reads 3333333333 Thread-0 reads CCCCCCCCCC Thread-1 reads CCCCCCCCCC Thread-5 reads CCCCCCCCCC Thread-3 reads CCCCCCCCCC Thread-4 reads CCCCCCCCCC Thread-2 reads CCCCCCCCCC Thread-0 reads dddddddddd Thread-1 reads dddddddddd Thread-5 reads dddddddddd Thread-3 reads dddddddddd Thread-4 reads dddddddddd Thread-2 reads dddddddddd