Read-Write Lock 模式
0. 描述了什么事邓馒?
使用一個人來專門控制鎖杉辙。
1. 類的說明,怎么抽象勋拟?
類名 | 說明 |
---|---|
Main |
啟動類 |
ReadWriteLock |
讀寫鎖類,該類提供了用于讀取和寫入的鎖 |
Data |
數(shù)據(jù)的抽象類妈候,保存 ReadWriteLock 的實例 |
ReaderThread |
保存 Data 的實例敢靡,并不斷讀取其內(nèi)容 |
WriterThread |
保存 Data 的實例,并不斷更新其內(nèi)容 |
2. 程序示例
1. Main.java
package read.write.lock;
public class Main {
public static void main(String[] args) {
Data data = new Data(10);
for (int i = 0; i < 6; i++) {
new ReaderThread(data).start();
}
new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
new WriterThread(data, "abcdefghijklmnopqrstuvwxyz").start();
}
}
2. ReadWriteLock.java
package read.write.lock;
public class ReadWriteLock {
private int readingReaders = 0;
private int writingWriters = 0;
private int waitingWriters = 0;
private boolean preferWriter = true;
public synchronized void readLock() throws InterruptedException {
// 判斷是否有線程正在進(jìn)行寫操作呢州丹,如果有的話醋安,那就等等吧
// 如果優(yōu)先寫操作杂彭,而且有寫線程在等待,那么也就先讓人家寫吧
while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
wait();
}
// 讀取線程計數(shù)加一
readingReaders++;
}
public synchronized void readUnlock() {
// 釋放掉讀取鎖吓揪,并且喚醒其他等待的線程亲怠,這里喚醒的是寫線程
readingReaders--;
preferWriter = true;
notifyAll();
}
public synchronized void writeLock() throws InterruptedException {
// 首先把寫線程放到隊列中
waitingWriters++;
try {
// 然后判斷是否有人正在寫或者正在讀,如果有的話柠辞,那就需要等等再寫
while (writingWriters > 0 || readingReaders > 0) {
wait();
}
} finally {
// 不管寫成功沒有团秽,都必須把等待線程給從等待隊列中去除掉
waitingWriters--;
}
// 開始寫了!
writingWriters++;
}
public synchronized void writeUnlock() {
// 釋放掉寫入鎖叭首,并且喚醒其他的寫入鎖和讀取鎖
writingWriters--;
preferWriter = false;
notifyAll();
}
}
3. ReaderThread.java
package read.write.lock;
public class ReaderThread extends Thread {
private final Data data;
public ReaderThread(Data data) {
this.data = data;
}
@Override
public void run() {
try {
while (true) {
char[] buffer = data.read();
System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(buffer));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4. WriterThread.java
package read.write.lock;
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() {
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);
index = (++index) % filler.length();
return c;
}
}