Read-Write Lock模式

適用的情況

多個(gè)線程共享了實(shí)例, 實(shí)例 是可變的, 對實(shí)例進(jìn)行讀的次數(shù)大于寫的次數(shù).多個(gè)線程可以同時(shí)讀, 但一段時(shí)間內(nèi)只能有一個(gè)線程可以進(jìn)行寫.

實(shí)現(xiàn)的方式

引入一個(gè)ReadWriteLock角色管理前來讀和寫的線程, 進(jìn)行互斥處理.

相關(guān)的模式

代碼示例:

示例介紹:ReaderThread負(fù)責(zé)讀取Data實(shí)例中的字符串, WriterThread每個(gè)一段時(shí)間向Data寫入字符串, ReadWriteLock注入Data中, 對Data的讀取和寫入方法加入了鎖.

Notice: 使用finally確保方法即使出現(xiàn)異常, 最后也能關(guān)閉掉鎖, 以防止出現(xiàn)死鎖.

package com.graphic.readWriteLock;

/**
 * @author youngxinler  19-6-1 下午7:49
 * @version 0.1
 **/

public final class ReadWriteLock {
    private int readingReaders = 0;
    private int waitingWriters = 0;
    private int writingWriters = 0;
    private boolean preferWriter = true;

    /*
     * 如果按照這樣來寫.
     *while (writingWriters > 0) {
     *     wait();
     *   }
     *讀進(jìn)程多于寫入進(jìn)程, 并且讀進(jìn)程是沒有互斥處理的, 也就是在一開始, 讀進(jìn)程就在占用住table,
     *即使有一個(gè)進(jìn)程在讀, 寫進(jìn)程就進(jìn)不來
     *
     */
    public synchronized void readLock() throws InterruptedException {
        while (writingWriters > 0 || (waitingWriters > 0 && preferWriter)) {
            wait();
        }
        notifyAll();
    }

    public synchronized void readUnlock() {
        readingReaders--;
        preferWriter = true;
        notifyAll();
    }

    //finally 確保
    public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;
        try {
            while (readingReaders > 0 || writingWriters > 0) {
                wait();
            }
        } finally {
            waitingWriters--;
        }
        writingWriters++;
    }

    public synchronized void writeUnlock() {
        writingWriters--;
        preferWriter = false;
        notifyAll();
    }
}
package com.graphic.readWriteLock;

import java.util.Random;

/**
 * @author youngxinler  19-6-1 下午8:07
 * @version 0.1
 **/

public class WriterThread extends Thread {
    private static final Random random = new Random();
    private final Data data;
    private final String filler;
    private int index = 0;

    public WriterThread(Data data, String filler) {
        this.data = data;
        this.filler = filler;
    }

    public void run() {
        try {
            while (true) {
                char c = nextChar();
                data.write(c);
                Thread.sleep(random.nextInt(3000));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private char nextChar() {
        char c = filler.charAt(index++);
        if (index >= filler.length()) {
            index = 0;
        }
        return c;
    }
}
package com.graphic.readWriteLock;

/**
 * @author youngxinler  19-6-1 下午8:12
 * @version 0.1
 **/

public class ReaderThread extends Thread {
    private final Data data;

    public ReaderThread(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        try {
            while (true) {
                char[] readbuf = data.read();
                System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readbuf));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.graphic.readWriteLock;



/**
 * @author youngxinler  19-6-1 下午7:49
 * @version 0.1
 **/

public class Data {
    private final char[] buffers;
    private final ReadWriteLock lock = new ReadWriteLock();

    public Data(int size) {
        this.buffers = new char[size];
        for (int i = 0; i < buffers.length; i++) {
            buffers[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 void doWrite(char c) {
        for (int i = 0; i < buffers.length; i++) {
            buffers[i] = c;
            slowly();
        }
    }


    private char[] doRead() {
        char[] newbuf = new char[buffers.length];
        for (int i = 0; i < buffers.length; i++) {
            newbuf[i] = buffers[i];
        }
        slowly();
        return newbuf;
    }

    private void slowly() {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.graphic.readWriteLock;

/**
 * @author youngxinler  19-6-1 下午8:15
 * @version 0.1
 **/

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, "ABCDEFG").start();
        new WriterThread(data, "abcdefg").start();
    }
}

點(diǎn)我,12種Java多線程設(shè)計(jì)模式, 希望能幫到你

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容