Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

Java多线程模式(三)

$
0
0

Read-Wirte Lock Pattern

        Read-Write Lock Pattern 将读取和写入分开来处理。在读取数据之前,必须获取用来读取的锁定。而要写入的时候,则必须获取用来写入的锁定。因为进行读取时,实例的状态不会改变,所以,就算有多个线程在同时读取也没有关系。但当有线程在进行写入的时候,不可以再进行写入的操作。写入的时候,实例的状态会改变。于是,当有一个线程在写入的时候,其他线程就不可以进行读取或写入。一般来说,进行共享互斥会使程序性能变差,但将写入的共享互斥与读取的共享互斥拆分开来,就可以提高程序的性能

public class ReadWriteLock {

    /**
     * 正在读取的线程数
     */
    private int     readingThreadsNumber;

    /**
     * 正在写入的线程数(最多为1)
     */
    private int     writingThreadsNumber;

    /**
     * 等待写入的线程数
     */
    private int     waitingWriteThreadsNumber;

    /**
     * 是否优先写入,true:优先写入;false:优先读取
     */
    private boolean preferWriter = true;

    public synchronized void readLock() throws InterruptedException {
        // 如果有线程正在写入或者优先写入时,有线程正在等待写入,读取线程则等待
        while (this.writingThreadsNumber > 0
                || (this.preferWriter && this.waitingWriteThreadsNumber > 0)) {
            wait();
        }

        this.readingThreadsNumber++;
    }

    public synchronized void readUnlock() throws InterruptedException {
        this.readingThreadsNumber--;
        this.preferWriter = true;
        notifyAll();
    }

    public synchronized void writeLock() throws InterruptedException {
        this.waitingWriteThreadsNumber++;
        // 如果有线程正在写入或者正在读取,当前写入线程等待
        try {
            while (this.writingThreadsNumber > 0 || this.readingThreadsNumber > 0) {
                wait();
            }
        } finally {
            this.waitingWriteThreadsNumber--;
        }

        this.writingThreadsNumber++;
    }

    public synchronized void writeUnlock() throws InterruptedException {
        this.writingThreadsNumber--;
        this.preferWriter = false;
        notifyAll();
    }

}

public class Data {

    private char[]        buffer;

    private ReadWriteLock readWriteLock = new ReadWriteLock();

    public Data(int size) {
        this.buffer = new char[size];
        for (int i = 0; i < size; i++) {
            this.buffer[i] = '*';
        }
    }

    public char[] read() throws InterruptedException {
        try {
            readWriteLock.readLock();
            return doRead();
        } finally {
            readWriteLock.readUnlock();
        }
    }

    public void write(char c) throws InterruptedException {
        try {
            readWriteLock.writeLock();
            doWrite(c);
        } finally {
            readWriteLock.writeUnlock();
        }
    }

    private char[] doRead() {
        char[] newChars = new char[buffer.length];
        System.arraycopy(this.buffer, 0, newChars, 0, this.buffer.length);
        slowly();
        return newChars;
    }

    private void doWrite(char c) {
        for (int i = 0; i < this.buffer.length; i++) {
            this.buffer[i] = c;
            slowly();
        }
    }

    private void slowly() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
    }
}


import java.util.Random;

public class ReaderThread extends Thread {

    private static final Random random = new Random();

    private final Data          data;

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

    @Override
    public void run() {
        while (true) {
            try {
                char[] c = data.read();
                System.out.println(Thread.currentThread().getName() + "reads " + String.valueOf(c));
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
    }

}


import java.util.Random;

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;
    }

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

    private char nextChar() {
        char c = filler.charAt(index);
        index++;
        if (index > filler.length()) {
            index = 0;
        }

        return c;
    }
}


public class MainThread {

    public static void main(String[] args) {
        int bufferSize = 10;
        Data data = new Data(bufferSize);

        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 ReaderThread(data).start();

        String filler1 = "abcdefghjklmnopqrstuvwxyz";
        String filler2 = "ABCDEFGHJKLMNOPQRSTUVWXYZ";
        new WriterThread(data, filler1).start();
        new WriterThread(data, filler2).start();

    }

}
        单纯使用Single Thread Execution Pattern时,就连read的操作一次也只有一条线程可以执行。如果read操作比较频繁或比较耗时,那使用Read-Write Lock Pattern会比Single Thread Execution Pattern好很多。但因为Read-Write Lock Pattern的程序比Single Thread Execution Pattern实现复杂,如果read操作很简单,那么使用Single Thread Execution Pattern可能性能反而较高。 Read-Write Lock Pattern的优点在于Reader参与者之间不会起冲突。不过,当wirte操作比较频繁时,Writer参与者会经常阻挡Reader参与者的进行,这样就无法展现Read-Write Lock Pattern的优点。

        在ReadWriteLock类中,提供了“读访问锁定”和“写访问锁定”两种逻辑上的锁定,但在“物理”上只用到了一个锁定,即ReadWriteLock实例的锁定。




Thread-Per-Message Pattern

待续。。。。

Worker Thread Pattern

待续。。。。
作者:shenzhen_liubin 发表于2013-8-8 23:38:07 原文链接
阅读:83 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>