写入是互斥的,读取是共享的,写入与读取不能同时发生。
类似缓存更新的场景。
缓存,多读多写,LRU淘汰。
读读共享,读写、写写互斥。
package ReadWriteLock;
public class ReadWriteLock {
private int waitWriters=0;
private int writingWriters=0;
private int readers=0;
//读写都在等待时,写优先,读线程多,写线程少,防止写线程被饿死
private boolean writeFirst=true;
public synchronized void readLock() throws InterruptedException{
while(writingWriters>0||(writeFirst&&waitWriters>0)){
wait();
}
readers++;
showDetail(Thread.currentThread().getName()+"--"+"readLock");
}
public synchronized void readUnlock(){
readers--;
writeFirst=true;
showDetail(Thread.currentThread().getName()+"--"+"readUnlock");
notifyAll();
}
public synchronized void writeLock() throws InterruptedException{
waitWriters++;
try{
//读、写过程中不能再写,等待
while(readers>0||writingWriters>0){
wait();
}
}finally{
waitWriters--;
}
writingWriters++;
showDetail(Thread.currentThread().getName()+"--"+"writeLock");
}
public synchronized void writeUnlock(){
//释放写锁
writingWriters--;
//写过,同时等待中的读、写中,读优先。避免连续写,读线程饥饿
writeFirst=false;
showDetail(Thread.currentThread().getName()+"--"+"writeUnlock");
notifyAll();
}
private void showDetail(String msg){
System.out.println(Thread.currentThread().getName()+"--"+"--------------------------");
System.out.println(Thread.currentThread().getName()+"--"+msg);
System.out.println(Thread.currentThread().getName()+"--"+"wait:"+waitWriters);
System.out.println(Thread.currentThread().getName()+"--"+"writing:"+writingWriters);
System.out.println(Thread.currentThread().getName()+"--"+"read:"+readers);
System.out.println(Thread.currentThread().getName()+"--"+"--------------------------");
}
}基于LinkedHashMap实现
package ReadWriteLock;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
public class SharedBuffer<K,V> {
private ReadWriteLock lock=new ReadWriteLock();
private LinkedHashMap<K,V> buf=null;
private final int size;
public SharedBuffer(final int initsize){
this.size=(int) Math.ceil(initsize / 0.75f) + 1;
this.buf=new LinkedHashMap<K,V>(size, 0.75f, true) {
private static final long serialVersionUID = -2347727619006196448L;
@Override
protected boolean removeEldestEntry(Entry<K,V> eldest) {
boolean isRemove=size() > initsize;
if(isRemove){
System.out.println(Thread.currentThread().getName()+"--"+eldest.getKey()+":"+eldest.getValue()+" 被丢弃!");
}
return isRemove;
}
};
}
public void put(K k,V v){
try {
lock.writeLock();
System.out.println(Thread.currentThread().getName()+"--"+"buffer after write lock");
System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
} catch (InterruptedException e) {
}
try{
this.buf.put(k, v);
System.out.println(Thread.currentThread().getName()+"--"+"buffer "+k+"->"+v);
}finally{
System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
lock.writeUnlock();
System.out.println(Thread.currentThread().getName()+"--"+"buffer after write unlock");
}
}
public V get(K k){
try {
System.out.println(Thread.currentThread().getName()+"--"+"buffer before read lock");
lock.readLock();
System.out.println(Thread.currentThread().getName()+"--"+"buffer after read lock");
} catch (InterruptedException e) {
}
try {
return this.buf.get(k);
}finally{
System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
lock.readUnlock();
System.out.println(Thread.currentThread().getName()+"--"+"buffer read unlock");
}
}
private String showSnapHost() {
Map<K,V> copy = new LinkedHashMap<K,V>(this.buf);
StringBuilder sb = new StringBuilder();
for (Map.Entry<K,V> entry : copy.entrySet()) {
sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
}
return sb.toString();
}
}package ReadWriteLock;
import java.util.Random;
public class Reader implements Runnable{
private final SharedBuffer<String,String> buf;
private final String myName;
public Reader(String myName,SharedBuffer<String,String> buf){
this.myName=myName;
this.buf=buf;
}
@Override
public void run() {
Random r=new Random();
while(true){
String k=Integer.toString(r.nextInt(10));
System.out.println(Thread.currentThread().getName()+"--"+k+" Readed!!! "+this.myName+":"+buf.get(k));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}package ReadWriteLock;
import java.util.Random;
public class Writer implements Runnable{
private final SharedBuffer<String,String> buf;
private final String myName;
public Writer(String myName,SharedBuffer<String,String> buf){
this.myName=myName;
this.buf=buf;
}
@Override
public void run() {
Random r=new Random();
int cnt=0;
while(true){
cnt++;
String k=null;
if(cnt<=10){
k=Integer.toString(r.nextInt(10));
}else{
k=Integer.toString(r.nextInt(100));
}
buf.put(k, ""+cnt);
System.out.println(Thread.currentThread().getName()+"--"+k+" writed!! "+this.myName+":"+cnt);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}package ReadWriteLock;
public class Test {
public static void main(String[] args) {
System.out.println("++++++++++++++++++++++++++++++++++++");
SharedBuffer<String,String> buf=new SharedBuffer<String,String>(10);
Reader r1=new Reader("r1",buf);
Reader r2=new Reader("r2",buf);
Writer w1=new Writer("w1",buf);
Writer w2=new Writer("w2",buf);
Thread rtd1=new Thread(r1);
Thread rtd2=new Thread(r2);
Thread wtd1=new Thread(w1);
Thread wtd2=new Thread(w2);
wtd1.start();
wtd2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
rtd1.start();
rtd2.start();
try {
rtd1.join();
rtd2.join();
wtd1.join();
wtd2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}本文出自 “JAVA技术栈笔记” 博客,请务必保留此出处http://stroll.blog.51cto.com/11038467/1857276
原文:http://stroll.blog.51cto.com/11038467/1857276