前言 :
Pattern 參予者 :
* Reader 參予者 :
* Writer 參予者 :
*SharedResource 參予者 :
ReadWriteLock 參予者 :
使用時機 :
使用範例 :
* ReadWriteLock 類別
這個類別用來提供SharedResource 讀取與寫入的鎖定, 其中當Shared Resource 有線程正在讀取時, 其他線程可以讀取, 但不能寫入; 當Shared Resource 有線程在寫入時, 其他線程不能讀取或寫入. 代碼如下 :* WriteThread 類別 :
WriteThread 類別表示用來對 Shared Resource (Data 類別) 寫入的線程, 代碼如下 :* ReaderThread 類別 :
ReadThread 類別用來模擬對 Shared Resource(Data 類別) 進行讀取的操作. 代碼如下 :* Data 類別 :
Data 類別用來模擬 Shared Resource, 可以被線程讀取與寫入, 代碼如下 :* Main 類別 :
Main 類別用來創建WriterThread類別, ReaderThread類別 與 Data 類別, 並進行Demo. 代碼如下 :
執行結果 :
補充說明 :
* 利用同時 “讀取” 不會衝突的特性, 提高程序的性能 : Read-Write Lock pattern 利用了 “讀取操作” 不會改變物件狀態的行為, 所以不需要進行共享互斥, 以提高程序的性能.
* 適合讀取操作頻繁 : 單存使用 Single Thread Execution Pattern, 就連 “讀取操作” 也進行共享互斥, 所有操作一次都只有一個線程進行, 雖然也可以完成 Read-Write Lock 的要求, 但在讀取頻繁的操作下, Read-Write Lock 所表現的性能相對會比較好.
* 鎖定的意義 : 使用 synchronized 可以獲取物件的鎖定, Java 程序的每一個物件各有一個鎖定, 同一個物件的鎖定無法由兩個或以上的線程獲取. 這是制定在Java語言規定裡, 實現在Java 的執行環境的機制. 因為是一開始就提供的功能, 所以我們稱為物理性的鎖定. Java 程序無法去改變這種鎖定行為. 相對的這章的 “讀取鎖定” 與 “寫入鎖定” 與使用 synchronized 獲取鎖定的意義上並不相同. 這不是Java 語言制定的機制, 而是由程序員自己實現的. 這就是所謂邏輯上的鎖定. 當程序員改寫 ReadWriteLock 類時, 就可以改變鎖定的機制.
Pattern 參予者 :
* Reader 參予者 :
* Writer 參予者 :
*SharedResource 參予者 :
ReadWriteLock 參予者 :
使用時機 :
使用範例 :
* ReadWriteLock 類別
這個類別用來提供SharedResource 讀取與寫入的鎖定, 其中當Shared Resource 有線程正在讀取時, 其他線程可以讀取, 但不能寫入; 當Shared Resource 有線程在寫入時, 其他線程不能讀取或寫入. 代碼如下 :
- package dp.thread.ch6;
- public class ReadWriteLock {
- private int readingReaders = 0; //(A)實際正在讀取的線程數目
- private int waitingWriters = 0; //(B)實際正在等待寫入的線程數目
- private int writingWriters = 0; //(C)實際正在寫入的線程數目
- private boolean preferWriter = true;
- public synchronized void readLock() throws InterruptedException {
- while(writingWriters > 0 || (preferWriter && waitingWriters > 0)){
- wait();
- }
- readingReaders++; // (A)正在讀取線程數目加一
- }
- public synchronized void readUnlock() {
- readingReaders--; // (A)正在讀取線程數目減一
- preferWriter = true;
- notifyAll();
- }
- public synchronized void writeLock() throws InterruptedException {
- waitingWriters++; // (B)正在等待寫入線程數目加一
- try{
- while (readingReaders > 0 || writingWriters >0) {
- wait();
- }
- }finally{
- waitingWriters--; // (B)正在等待寫入線程數目減一
- }
- writingWriters++; // (C)實際寫入線程數目加一
- }
- public synchronized void writeUnlock() {
- writingWriters--; // (C)實際寫入線程數目減一
- preferWriter = false;
- notifyAll();
- }
- }
WriteThread 類別表示用來對 Shared Resource (Data 類別) 寫入的線程, 代碼如下 :
- package dp.thread.ch6;
- import java.util.Random;
- public class WriteThread extends Thread{
- private static final Random random = new Random();
- private final Data data;
- private final String filter;
- private int index = 0;
- public WriteThread(Data data, String filter) {
- this.data = data;
- this.filter = filter;
- }
- public void run(){
- try{
- while(true) {
- char c = nextChar();
- data.write(c);
- System.out.println(Thread.currentThread().getName()+" writes "+c+" success!");
- Thread.sleep(random.nextInt(1000));
- if(index <0 ){
- break;
- }
- }
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- private char nextChar(){
- char c = filter.charAt(index);
- index++;
- if(index >= filter.length()) {
- index = -1;
- }
- return c;
- }
- }
ReadThread 類別用來模擬對 Shared Resource(Data 類別) 進行讀取的操作. 代碼如下 :
- package dp.thread.ch6;
- import java.util.Random;
- public class ReaderThread extends Thread{
- private final Data data;
- private int time = 10;
- private static final Random random = new Random();
- public ReaderThread(Data data, int t) {
- this.data = data;
- if(t>0) {
- time = t;
- }
- }
- public void run(){
- int i=0;
- try{
- while(i
- Thread.sleep(random.nextInt(1500));
- char[] readBuf = data.read();
- System.out.println(Thread.currentThread().getName()+" reads "+String.valueOf(readBuf)+" for "+(i+1)+"times/"+time);
- i++;
- }
- }catch(InterruptedException ie){
- ie.printStackTrace();
- }
- }
- }
Data 類別用來模擬 Shared Resource, 可以被線程讀取與寫入, 代碼如下 :
- package dp.thread.ch6;
- public class Data {
- private final char[] buffer;
- private final ReadWriteLock lock = new ReadWriteLock();
- public Data(int size){
- this.buffer = new char[size];
- for(int i=0;i
- buffer[i] = '*';
- }
- }
- public char[] read() throws InterruptedException {
- lock.readLock();
- try{
- return doRead();
- }finally{
- lock.readUnlock();
- }
- }
- public void write(char c) throws InterruptedException{
- lock.writeLock();
- try{
- doWrite(c);
- }finally{
- lock.writeUnlock();
- }
- }
- private char[] doRead(){
- char[] newbuf = new char[buffer.length];
- for(int i=0;i
- newbuf[i] = buffer[i];
- }
- slowly();
- return newbuf;
- }
- private void doWrite(char c) {
- for(int i=0;i
- buffer[i] = c;
- slowly();
- }
- }
- private void slowly(){
- try{
- Thread.sleep(50);
- }catch(InterruptedException ie){
- ie.printStackTrace();
- }
- }
- }
Main 類別用來創建WriterThread類別, ReaderThread類別 與 Data 類別, 並進行Demo. 代碼如下 :
- package dp.thread.ch6;
- public class Main {
- public static void main(String args[]) {
- Data data = new Data(10);
- new ReaderThread(data,20).start();
- new ReaderThread(data,25).start();
- new ReaderThread(data,30).start();
- new ReaderThread(data,15).start();
- new ReaderThread(data,10).start();
- new ReaderThread(data,5).start();
- new WriteThread(data,"abcdefghijklmnopqrstuvwxyz").start();
- new WriteThread(data,"ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
- }
- }
執行結果 :
補充說明 :
* 利用同時 “讀取” 不會衝突的特性, 提高程序的性能 : Read-Write Lock pattern 利用了 “讀取操作” 不會改變物件狀態的行為, 所以不需要進行共享互斥, 以提高程序的性能.
* 適合讀取操作頻繁 : 單存使用 Single Thread Execution Pattern, 就連 “讀取操作” 也進行共享互斥, 所有操作一次都只有一個線程進行, 雖然也可以完成 Read-Write Lock 的要求, 但在讀取頻繁的操作下, Read-Write Lock 所表現的性能相對會比較好.
* 鎖定的意義 : 使用 synchronized 可以獲取物件的鎖定, Java 程序的每一個物件各有一個鎖定, 同一個物件的鎖定無法由兩個或以上的線程獲取. 這是制定在Java語言規定裡, 實現在Java 的執行環境的機制. 因為是一開始就提供的功能, 所以我們稱為物理性的鎖定. Java 程序無法去改變這種鎖定行為. 相對的這章的 “讀取鎖定” 與 “寫入鎖定” 與使用 synchronized 獲取鎖定的意義上並不相同. 這不是Java 語言制定的機制, 而是由程序員自己實現的. 這就是所謂邏輯上的鎖定. 當程序員改寫 ReadWriteLock 類時, 就可以改變鎖定的機制.
This message was edited 4 times. Last update was at 05/01/2010 16:22:52
沒有留言:
張貼留言