プログラム悪戦苦闘日記

はてなダイアリーからの移行(遺物)

スレッドデザインパターン - 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