Java并发之读者-写者几种实现

来源:互联网 发布:免费商城系统 php 编辑:程序博客网 时间:2024/04/27 18:12

读者写者经典同步问题的原理算法就不再详细说了!下面给出Java并发写的几种实现,希望支持!

第一种实现:synchronized

DateFile.java

public class DateFile {// readCount表示正在读的人数,初值为0,表示还没有人读。private int readerCount;// doreading表示读信号量,当doreading=true时不能进行写操作。private boolean doreading;// dowriting表示写信号量,当dowriting=ture时不能进行读操作。private boolean dowriting;public DateFile() {readerCount = 0;doreading = false;dowriting = false;}// 线程睡眠,不消耗CPU资源public static void naps() {try {Thread.sleep((int) (4000 * Math.random()));} catch (InterruptedException e) {e.printStackTrace();}}public synchronized int startRead() {// 开始读操作while (dowriting == true) {try {System.out.println(Thread.currentThread().getName()+" is waiting");// 等待写者发出notifywait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+" begin to read!");readerCount++;if (readerCount == 1) {doreading = true;}return readerCount;}public synchronized int endRead() {// 结束读操作--readerCount;if (readerCount == 0) {doreading = false;}notifyAll();System.out.println(Thread.currentThread().getName()+" reading done!");return readerCount;}public synchronized void startWrite() {// 开始写操作while (doreading == true || dowriting == true) {try {System.out.println(Thread.currentThread().getName()+" is waiting");wait();// 等待写者或读者发出notify} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+" begin to write!");dowriting = true;}public synchronized void endWrite() {// 结束写操作dowriting = false;notifyAll();System.out.println(Thread.currentThread().getName()+" writing done!");}}
Reader.java

public class Reader implements Runnable {private int readerNum;private DateFile df;public Reader(int readerNum, DateFile df) {this.readerNum = readerNum;this.df = df;}public void run() {//while (true) {System.out.println("reader " + readerNum + " comes here");df.naps();df.startRead();df.naps();df.endRead();//}}}
Writer.java

public class Writer implements Runnable {private DateFile df;private int writerNum;public Writer(int writerNum, DateFile df) {this.df = df;this.writerNum = writerNum;}public void run() {//while (true) {System.out.println("Writer " + writerNum + " comes here");df.naps();df.startWrite();df.naps();df.endWrite();//}}}

WriterReader.java  (main方法)

public class WriterReader {public static void main(String[] args) {DateFile df = new DateFile();Reader r1 = new Reader(1, df);Reader r2 = new Reader(2, df);Reader r3 = new Reader(3, df);Reader r4 = new Reader(4, df);Writer w1 = new Writer(1, df);Writer w2 = new Writer(2, df);    Writer w3 = new Writer(3, df);    new Thread(r1, "读者线程 r1").start();    new Thread(r2, "读者线程r2").start();    new Thread(r3, "读者线程r3").start();    new Thread(r4, "读者线程r4").start();    new Thread(w1, "写者线程w1").start();    new Thread(w2, "写者线程w2").start();    new Thread(w3, "写者线程w3").start();}}

输出结果:

reader 1 comes herereader 2 comes herereader 4 comes hereWriter 2 comes herereader 3 comes hereWriter 1 comes hereWriter 3 comes here读者线程r2 begin to read!读者线程 r1 begin to read!读者线程r2 reading done!写者线程w3 is waiting写者线程w1 is waiting读者线程r4 begin to read!读者线程r3 begin to read!读者线程r4 reading done!写者线程w1 is waiting写者线程w3 is waiting写者线程w2 is waiting读者线程 r1 reading done!写者线程w2 is waiting写者线程w3 is waiting写者线程w1 is waiting读者线程r3 reading done!写者线程w1 begin to write!写者线程w3 is waiting写者线程w2 is waiting写者线程w1 writing done!写者线程w2 begin to write!写者线程w3 is waiting写者线程w2 writing done!写者线程w3 begin to write!写者线程w3 writing done!

第二种实现:Lock和semaphore的实现

Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。

import java.util.concurrent.Executor;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.locks.ReentrantLock;public class Main {    private final ReentrantLock lock ;   //定义锁    private static int readCount = 0;    //读者的数量    private Semaphore writeSemaphore ;   //写信号量    public Main() {        lock = new ReentrantLock();        writeSemaphore = new Semaphore(1);    }    public static void main(String[] args) {        Main main = new Main();        Executor executors = Executors.newFixedThreadPool(4);        executors.execute(main.new Reader());        executors.execute(main.new Reader());        executors.execute(main.new Writer());        executors.execute(main.new Reader());    }    class Reader implements Runnable {        @Override        public void run() {            before();             //读操作之前的操作            read();               //读操作            after();             //读操作之后的操作        }        public void before() {    //读操作之前的操作            final ReentrantLock l = lock;            l.lock();            try {                if(readCount == 0) {   //当有读者时,写者不能进入                    writeSemaphore.acquire(1);                }                readCount += 1;                System.out.println("有1位读者进入");            } catch (InterruptedException e) {                e.printStackTrace();            } finally {                l.unlock();            }        }        public void read() {         //读操作            System.out.println("当前有 " + readCount + " 位读者");        }        public void after() {        //读操作之后的操作            final ReentrantLock l = lock;            l.lock();            try {                readCount -= 1;                System.out.println("有1位读者离开" );                if(readCount == 0)     //当读者为0时,写者才可以进入                      writeSemaphore.release(1);            } finally {                l.unlock();            }        }    }    class Writer implements Runnable {        @Override        public void run() {            final ReentrantLock l = lock;            l.lock();            try {                try {                    writeSemaphore.acquire(1);     //同时只有一个写者可以进入                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("写者正在写");                writeSemaphore.release(1);            }  finally {                l.unlock();            }        }    }}

另外:见到一种更好理解的实现方式,用synchronized来实现,原子性地实现信号量的PV操作

class Semaphore{int value;public Semaphore(int v){this.value = v;}public synchronized void p(){value = value-1;if(value<0){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void v(){value = value+1;if(value<=0){this.notifyAll();}}}
class Reader implements Runnable{int count;Semaphore rmutex;Semaphore wmutex;public Reader(int c,Semaphore r,Semaphore w){this.count = c;this.rmutex = r;this.wmutex = w;}public void run(){while(true){rmutex.p();if(count == 0) wmutex.p();//当第一读进程欲读数据库时,阻止写进程写count++;rmutex.v();System.out.println(count+" begin read data");rmutex.p();count--;System.out.println(count+" finish read data");if(count == 0) wmutex.v();//当最后一个读进程读完数据库时,运行写进程写rmutex.v();}}}class Writer implements Runnable{Semaphore wmutex;public Writer(Semaphore w){this.wmutex = w;}public void run(){while(true){wmutex.p();System.out.println("begin write data");System.out.println("finish write data");wmutex.v();try {Thread.sleep((long) (Math.random()*1000));} catch (InterruptedException e) {e.printStackTrace();}}}}public class ReaderWriter{public static void main(String[] args){int count = 0;Semaphore rmutex = new Semaphore(1);Semaphore wmutex = new Semaphore(1);Reader reader = new Reader(count,rmutex,wmutex);Writer writer = new Writer(wmutex);Thread r = new Thread(reader);Thread r1 = new Thread(reader);Thread w = new Thread(writer);Thread w1 = new Thread(writer);w1.start();r.start();w.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}r1.start();}}




1 0
原创粉丝点击