【Java】【OS】读者写者问题代码通过应用小程序动态页面实现

📢博客主页:🏀九九舅舅酒酒🏀
📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论!👏
📢本文由 【九九舅舅酒酒】 原创,首发于 CSDN🙉🙉🙉
📢由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!✨
📖精品专栏(不定时更新)【JavaSE】 【MySQL】【LeetCode】【Web】【操作系统】


运行效果截图:

目录

一、问题描述:

二、问题分析:

三、代码实现

(1)

(2)

(3)

(4)

(5)

(6)



 

 

一、问题描述:

有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。


二、问题分析:

由上面的文字描述来看,读者和写者之间是互斥的,写者和写者之间是互斥的,为了满足可以多个读者进行读操作,我们可以设置一个记录型信号量readcount表示正在读的进程数目,同时定义一个互斥信号量wmutex,实现写写互斥和读写互斥,再定义一个remutex来保证进程间互斥访问readcount(因为readcount是被多个进程共享的,所以需要互斥方式来访问)


三、代码实现

(1)

import java.awt.*;

public class DataBaseBuffer extends Canvas implements Runnable{
	int[] readWantQ;
	int[] writerWantQ;
	int frameDelay = 2560;

	private int[] buffer;
	private int[] readersQ;
	private int writerID;
	private boolean readLock  = false;		//is reading
	private boolean writeLock = false;		//is writting
	private int readerCount;
	private int readerWantCount, writerWantCount;
	private int writerCount;

	private int readTop, readBottom, writerTop, writerBottom, nums, size;
	private Font font;
	private FontMetrics fm;
	private int x;     					//reader consumed item

	public DataBaseBuffer( ){
		size = 5;    					//defualt buffer size
		nums = 0;
		readTop 	= readBottom  = writerTop 		= writerBottom 	  = 0;
		readerCount = writerCount = readerWantCount = writerWantCount = 0;
		setSize(size);
		resize(500, 300);
		setBackground(Color.white);
		font = new Font("TimesRoman", Font.BOLD, 18);
		fm	 = getFontMetrics(font);
 	 }

	public void run(){
		while(true) {
			try{
				Thread.sleep(frameDelay);
			}catch(InterruptedException e){}
			repaint();
		}
	}

	public void setSize(int s)
	{
		size 		= s;
		buffer  	= new int[size];
		readWantQ 	= new int[size];
		writerWantQ = new int[size];
		readersQ 	= new int[size];
		repaint();
	}

	public synchronized void acquireReadLock(ReaderWriter applet, int id)
	{
		readWantQ[readTop] = id;     //nums is the index for readWantQ
		readTop = (readTop+1) % size;
		readerWantCount ++;
		repaint();
		applet.r[id].status = 4;    //want in
		applet.mb.println(applet.r[id].status, "r", id);

		try{
			applet.r[id].sleep((int) (Math.random()*frameDelay));
			}catch(InterruptedException e) {}

		while(readWantQ[readBottom] != id)
		{
			try{
					applet.r[id].status = 1;
					applet.mb.println(applet.r[id].status, "r", id);
					wait();
				}catch(InterruptedException e) {
					System.err.println("Execption " +  e.toString());
			    }
		}
		if(applet.writerPriority)
		{
			while(writerWantCount != 0)		//if there is a writer is waitting
			{
				try{
					applet.r[id].status = 5;
					applet.mb.println(applet.r[id].status, "r", id);
					wait();
			   		}catch(InterruptedException e) {
				   		System.err.println("Execption " +  e.toString());
			    	}
			}//end of while loop
		}//end of if statement

		while(writeLock)		//if there is any writer is writting
		{
			try{
				applet.r[id].status = 1;
				System.out.println("reader " + id + " is waitting");
				applet.mb.println(applet.r[id].status, "r", id);
				wait();
			}catch(InterruptedException e){
				System.err.println("Execption " +  e.toString());
		    }
		}

		if(readLock == false)
		{
			readLock = true;
			System.out.println("Reader " + id + "locked the buffer");
	    }

		readBottom = (readBottom+1) %size;
		readersQ[nums] = id;
		nums = (nums + 1) % size;
		readerWantCount --;
		readerCount++;
		repaint();
		applet.r[id].status = 2;
		applet.mb.println(applet.r[id].status, "r", id);
		System.out.println("Reader "+id + "is reading");
		notifyAll();
	}

	public synchronized void releaseReadLock(ReaderWriter applet,int id)
	{
			readerCount --;
			if(readerCount == 0) 		//the last reader release the lock
			{ 		readLock = false;
					System.out.println("Reader " + id + "released the lock");
			}
			applet.r[id].status = 7;
			applet.mb.println(applet.r[id].status, "r", id);
			System.out.println("readerCount is " + readerCount);
			notifyAll();
	}

	public synchronized void acquireWriteLock(ReaderWriter applet, int id)
	{
		writerWantQ[writerTop] = id;
		writerTop=(writerTop+1)%size;
		applet.w[id].status = 4;  //want in
		applet.mb.println(applet.w[id].status, "w", id);
		writerWantCount ++;
		repaint();
		try{ applet.w[id].sleep(frameDelay); }
		catch(InterruptedException e) {}

		/** if the writer already be stopped, give the chance to other writers **/
		if(applet.w[id].status == 3)
		{
			writerWantQ[writerBottom] = 0;
			writerBottom = (writerBottom +1) %size;
			System.out.println("writerBottom has been updated after check the writerIndex");
		}

		while(writerWantQ[writerBottom] != id)
		{
			try {
					applet.w[id].status = 6;
					applet.mb.println(applet.w[id].status, "w", id);
					System.out.println("Writer " + id + " is waitting for the turn");
					wait();
				}catch(InterruptedException e){
					System.err.println("Execption " +  e.toString());
			    }
		}

		if(applet.readerPriority)
		{
			while(readerWantCount != 0)
			{
				try{	applet.w[id].status = 5;
						applet.mb.println(applet.w[id].status, "w", id);
						System.out.println("Writer "+id + " is waitting ");
						//repaint();
						wait();
					}catch(InterruptedException e){
						System.err.println("Execption " +  e.toString());
			    	}
			}//end of while loop
		}//end of if

	  while(readLock || writeLock)
	   {
			try{
					applet.w[id].status = 1;
					applet.mb.println(applet.w[id].status, "w", id);
					System.out.println("Writer "+id + " is waitting for the lock");
					//repaint();
					wait();
				}catch(InterruptedException e){
					System.err.println("Execption " +  e.toString());
		       }
		}

		writeLock = true;
		notifyAll();
		writerWantQ[writerBottom] = 0;
		writerBottom = (writerBottom + 1)%size;
		writerID = id;
		writerWantCount --;
		writerCount++;
		repaint();
		applet.w[id].status = 2;
		applet.mb.println(applet.w[id].status, x, "w", id);
	}

	public synchronized void releaseWriteLock(ReaderWriter applet, int id)
	{
		        System.out.println("Writer " + id + " released the lock");
		        writerCount --;
				applet.w[id].status = 7;
				applet.mb.println(applet.w[id].status, x, "w", id);
				writeLock = false;
				notifyAll();
   }


	public void clear()
	{
		size			= 5;
		writerBottom 	= writerTop = 0;
		readBottom 		= readTop 	= 0;
		writerWantCount = 0;
		readerWantCount = 0;
		readerCount 	= 0;
		writerCount 	= 0;
		readLock 		= writeLock = false;
		nums 			= 0;
		buffer 			= new int[size];
		readWantQ 		= new int[size];
		writerWantQ 	= new int[size];
		readersQ 		= new int[size];
		//repaint();
	}

	/* print the queue on the canvas */
	public void paint(Graphics g){
		int xpos = 630;
		int ypos = 5;
		g.setFont(new Font("TimesRoman", Font.BOLD, 11));
		g.setColor(Color.green);
		g.draw3DRect(xpos, ypos, 10, 10, true);
		g.fillRect(xpos, ypos, 10, 10);
		g.drawString("Reading", xpos+15, ypos+10);
		g.setColor(Color.red);
		g.draw3DRect(xpos, ypos+14, 10, 10, true);
		g.fillRect(xpos, ypos+14, 10, 10);
		g.drawString("Writing", xpos+15, ypos+25);
		g.setColor(Color.blue);
		g.draw3DRect(xpos, ypos+28, 10, 10, true);
		g.fillRect(xpos, ypos+28, 10, 10);
		g.drawString("Empty", xpos+15, ypos+40);

		g.setFont(new Font("TimesRoman", Font.BOLD, 14));
		g.setColor(Color.blue);
		xpos = 40;
		ypos = 50;
		g.drawString("Want in Readers", xpos-5, ypos-10);
		g.drawString("Want in Writers", xpos+455, ypos-10);

		/** Draw Want-In readers queue on canvas **/
		int i = readBottom;
		System.out.println("readBottom is: " + readBottom);
		for(int j=0; j< readerWantCount; j++)
		{
			g.drawString(Integer.toString(readWantQ[i]), xpos+30, ypos+15+25*j);
			g.draw3DRect(xpos+20,ypos+25*j, 22, 22, true);
			i = (i+1) % size;
		}

		/** Draw Want-In writers queue on canvas **/
		i = writerBottom;
		for(int j=0; j< writerWantCount; j++)
		{
			g.drawString(Integer.toString(writerWantQ[i]), xpos+507, ypos+15+25*j);
			g.draw3DRect(xpos+500,ypos+25*j, 22, 22, true);
			i = (i+1) % size;
		}

		/** Draw database buffer on canvas      **/
		if(readLock) 	     		g.setColor(Color.green);
		else if(writeLock) 		    g.setColor(Color.red);
		else                 		g.setColor(Color.blue);

		g.draw3DRect(xpos+250, ypos+20, 100, 100, true);
		g.fillRect(xpos+250, ypos+20, 100, 100);
		if(readLock)
		{
			g.setColor(Color.black);
			g.drawString("Reading", xpos + 270, ypos+60);
		}
		else if(writeLock)
		{
			g.setColor(Color.black);
			g.drawString("W " +Integer.toString(writerID), xpos + 280, ypos+45);
			g.drawString("Writting", xpos + 270, ypos+60);
		}
	}
}

/*  File: DataBaseBuffer.java
 *
 *  This is a the main program which contains the algorithm controls execution of
 *  readers and writers. It also provide animation canvas to the applet class.
 *  Readers can access the shared buffer simultaneously, but the writers have to access
 *  the shared buffer exclusively.
 *
 *  The want-to-in readers and writers will wait in a queue in the order of their arrival
 *  first, then try to acquire the lock to access the shared data buffer.
 *
 *  If the user chooses "Same Priority", the readers and writers will access the
 *  shared data buffer in the order of their arrival. If there is any writer arrived
 *  before the waiting reader(s), the waiting reader(s) cannot access the shared data even
 *  there is a reader reading.
 *
 *  If the user chooses "Readers have Priority", the writers have to give up their chances
 *  if there is any reader is waiting in the queue. In this situation, the writers may
 *  experience the starvation.
 *
 *  If the user chooses "Writers have Priority", the readers have to give up their chances
 *  if there is any writer is waiting in the queue. In this situation, the readers may
 *  experience the starvation.
 *
 */

(2)




import java.awt.*;

public class DataBaseBuffer extends Canvas{
	int[] readWantQ;
	int[] writerWantQ;
	String[] wantQ;
	int frameDelay = 1560;

	private int writerID;
	private int readerCount;
	private int wantCount;
	private int readerWantCount, writerWantCount;
	private int writerCount;
	private int wn, rn; 					// the number of readers and writers
	private int readTop, readBottom, writerTop, writerBottom;
	private int wantTop, wantBottom;
	private Font font;
	private FontMetrics fm;
	private boolean readLock  = false;
	private boolean writeLock = false;

	public DataBaseBuffer( ){

		resize(500, 300);
		setBackground(Color.white);
		font = new Font("TimesRoman", Font.BOLD, 18);
		fm	 = getFontMetrics(font);
 	 }

	public void setSize(int readerN, int writerN)
	{
		rn = readerN;
		wn = writerN;

		readTop 	= readBottom  = writerTop 		= writerBottom 	  = 0;
		readerCount = writerCount = readerWantCount = writerWantCount = 0;
		wantTop 	= wantBottom  = 0;
		wantCount   = 0;
		writerID	= 0;
		readLock	= false;
		writeLock 	= false;
		wantQ		= new String[rn+wn];
		writerWantQ = new int[wn];
		readWantQ	= new int[rn];
		repaint();

	}

	/* The waiting queue is implemented as an array to handle the "Writers have Priority"
	 * and "Readers have Priority" situation more easily.
	 */
	public synchronized void enterQueue(String s, int id)
	{
		wantQ[wantTop] = s + id;
		wantTop ++;
		wantCount ++;
		repaint();
	}

	public synchronized void dequeue(String s, int id )
	{
		String str;
		str = s+id;
		while(!wantQ[0].equals(str))
		{
			try{ wait(); } catch(InterruptedException e) { }
		}
		for(int i = 0; i < (wantTop-1); i++)
		{
			wantQ[i] = wantQ[i+1];
		}
		wantTop --;
		wantCount --;
		repaint();
	}

	/* This method is to move the writer ahead in "Writers have Priority" situation.
	 * Or move the reader ahead in "Readers have Priority" situation.
	 */
	public synchronized void changePosition(String s, int id)
	{
		String str;
		String tmp;

		int pos = 0;     	//to find the posting of 1st writer
		String wtr;
		wtr = s+id;


		while(!(wantQ[pos].equals(wtr)))
		{
			pos++;
		}

		for(int i = 0; i < wantTop; i++)
		{
			System.out.println(wantQ[i]);
		}
		str = wantQ[pos];
		for(int i = pos; i > 0; i--)
		{
			wantQ[i] = wantQ[i-1];
		}
		wantQ[0] = str;
		repaint();
		for(int i = 0; i < wantTop; i++)
		{
			System.out.println(wantQ[i]);
		}
	}


	public synchronized boolean hasWriterWant()
	{
		return (writerWantCount > 0);
	}

	public synchronized boolean hasReaderWant()
	{
		return (readerWantCount > 0);
	}

	public synchronized void acquireReadLock(ReaderWriterApplet applet, int id)
	{
		readWantQ[readTop] = id;     //nums is the index for readWantQ
		readTop = (readTop+1) % rn;
		readerWantCount ++;
		repaint();
		notifyAll();
		enterQueue("R", id);
		applet.r[id].status = 1;    //want in
		applet.mc.println(applet.r[id].status, "r", id);
		try{	applet.r[id].sleep(frameDelay);	}catch(InterruptedException e) {}

		if(applet.writerPriority)
		{
			while(hasWriterWant() || writeLock)
			{
				applet.r[id].status = 3;
				applet.mc.println(applet.r[id].status, "r", id);
				try{ wait(); } catch(InterruptedException e) { }
			}//end of while loop
		}//end of if statement
		else if(applet.readerPriority)
		{
			while(readWantQ[readBottom] != id)
			{
				try { wait(); } catch(InterruptedException e) {}
			}
			changePosition("R",id);
		}
		else
		{
			applet.r[id].status = 3;
			applet.mc.println(applet.r[id].status, "r", id);
			while(!wantQ[wantBottom].equals("R"+id))
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
		}

		while(writeLock)		//if there is any writer is writing
		{
			applet.r[id].status = 3;
			applet.mc.println(applet.r[id].status, "r", id);
			try{ wait(); } catch(InterruptedException e) { }
		}

		if(readLock == false)
		{
			readLock = true;
			notifyAll();
	    }

		readBottom = (readBottom+1) %rn;
		readerWantCount --;
		dequeue("R", id);
		readerCount ++;
		repaint();
		applet.r[id].status = 2;
		applet.mc.println(applet.r[id].status, "r", id);
		System.out.println("Reader "+id + "is reading");
		notifyAll();
	}

	public synchronized boolean hasReader()
	{
		return (readerCount > 0);
	}
	public synchronized void releaseReadLock(ReaderWriterApplet applet,int id)
	{
			readerCount --;
			notifyAll();
			if(!hasReader())
			{
				readLock = false;
				notifyAll();
				applet.r[id].status = 4;
				applet.mc.println(applet.r[id].status, "r", id);
			}
			repaint();
	}

	public synchronized void acquireWriteLock(ReaderWriterApplet applet, int id)
	{
		writerWantQ[writerTop] = id;
		writerTop=(writerTop+1)%wn;
		writerWantCount ++;
		notifyAll();
		repaint();
		enterQueue("W", id);
		applet.w[id].status = 1;  				//want in
		applet.mc.println(applet.w[id].status, "w", id);
		try{ applet.w[id].sleep(frameDelay); }catch(InterruptedException e) {}


		if(applet.writerPriority)
		{
			while(writerWantQ[writerBottom] != id)
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
			/* change the  positions of writer and other readers */
			changePosition("W", id);
			while(readLock || writeLock)
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
		}
		else if(applet.readerPriority)
		{
			while(!(wantQ[wantBottom].equals("W"+id)) || hasReaderWant() || readLock || writeLock)
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
			System.out.println("Writer "+ id + " move forward");
		}
		else
		{
			while(!(wantQ[wantBottom].equals("W"+id)))
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
			while(readLock || writeLock)
			{
				try{ wait(); } catch(InterruptedException e) { }
			}
		}

		writeLock = true;
		System.out.println("Writer "+ id+ " Got the lock ******");
		notifyAll();
		dequeue("W", id);
		writerBottom = (writerBottom + 1)%wn;
		writerID = id;
		writerWantCount --;
		writerCount++;
		notifyAll();
		repaint();
		applet.w[id].status = 2;
		applet.mc.println(applet.w[id].status, "w", id);
	}

	public synchronized void releaseWriteLock(ReaderWriterApplet applet, int id)
	{
		        System.out.println("Writer " + id + " released the lock");
		        writerCount --;
				writerID  = 0;
				writeLock = false;
				notifyAll();
				repaint();
    }


	public void clear()
	{
		writerBottom 	= writerTop = 0;
		readBottom 		= readTop 	= 0;
		writerWantCount = 0;
		readerWantCount = 0;
		readerCount 	= 0;
		writerCount 	= 0;
		readLock 		= writeLock = false;

		writerWantQ 	= new int[wn];
		readWantQ 		= new int[rn];
		wantQ			= new String[wn+rn];
		wantTop 		= wantBottom = 0;
	}

	/* print the queue on the canvas */
	public void paint(Graphics g){
		int xpos = 630;
		int ypos = 5;
		g.setFont(new Font("TimesRoman", Font.BOLD, 11));
		g.setColor(Color.green);
		g.draw3DRect(xpos, ypos, 10, 10, true);
		g.fillRect(xpos, ypos, 10, 10);
		g.drawString("Reading", xpos+15, ypos+10);
		g.setColor(Color.red);
		g.draw3DRect(xpos, ypos+14, 10, 10, true);
		g.fillRect(xpos, ypos+14, 10, 10);
		g.drawString("Writing", xpos+15, ypos+25);
		g.setColor(Color.blue);
		g.draw3DRect(xpos, ypos+28, 10, 10, true);
		g.fillRect(xpos, ypos+28, 10, 10);
		g.drawString("Empty", xpos+15, ypos+40);

		g.setFont(new Font("TimesRoman", Font.BOLD, 14));
		g.setColor(Color.blue);
		xpos = 40;
		ypos = 50;
		g.drawString("Waiting Queue", xpos-5, ypos-20);

		/** Draw want-in queue on the top of canvas **/
		int i = wantBottom;
		for(int j = 0; j < wantCount; j++)
		{
			if(	wantQ[i].equals("W1") || wantQ[i].equals("W2")
			  ||wantQ[i].equals("W3")|| wantQ[i].equals("W4")
			  ||wantQ[i].equals("W5"))
			{
				g.setColor(Color.red);
				g.drawString(wantQ[i], xpos+450-30*j, ypos-18);
				g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);
			}
			if( wantQ[i].equals("R1") || wantQ[i].equals("R2")
			  ||wantQ[i].equals("R3")|| wantQ[i].equals("R4")
			  ||wantQ[i].equals("R5"))
			  {
				g.setColor(Color.green);
				g.drawString(wantQ[i], xpos+450-30*j, ypos-18);
				g.draw3DRect(xpos+445-30*j, ypos-35, 28, 28, true);
			  }
			i = (i+1) % (wn+rn);
		}

		/** Draw database buffer on canvas      **/
		if(readLock) 	     		g.setColor(Color.green);
		else if(writeLock) 		    g.setColor(Color.red);
		else                 		g.setColor(Color.blue);

		g.draw3DRect(xpos+250, ypos+20, 100, 100, true);
		g.fillRect(xpos+250, ypos+20, 100, 100);
		if(readLock)
		{
			g.setColor(Color.black);
			g.drawString("Reading", xpos + 270, ypos+60);
		}
		else if(writeLock)
		{
			g.setColor(Color.black);
			g.drawString("W " +Integer.toString(writerID), xpos + 280, ypos+45);
			g.drawString("Writing", xpos + 270, ypos+60);
		}
	}
}

(3)

/* File: MessageCanvas.java
 *
 * This class provides message canvas for the applet GUI.
 * It will print the statuses of readers and writers on the GUI.
 *
 */

import java.awt.*;

class MessageCanvas extends Canvas
{
	private Font font;
	private FontMetrics fm;
	private int[] writerStatus;
	private int[] readerStatus;
	private int msgHeight;
    private int msgWidth;
	private int pn, cn;
	private int frameDelay = 256;

	public MessageCanvas( )
	{
		resize(size().width, 50);
		setBackground(Color.green);
		font = new Font("TimesRoman", 1, 18);
		fm = getFontMetrics(font);
        msgHeight = fm.getHeight();

	}

   public void setMessage(int writerN, int readerN)
    {
		pn = writerN;
		cn = readerN;
		writerStatus = new int[pn+1];
		readerStatus = new int[cn+1];
		repaint();
    }


    void println(String s)
    {
        msgWidth = fm.stringWidth(s);
        repaint();
    }

    void println(int s, String st, int id)
	{
	        if(st.equals("w"))
			 	writerStatus[id] = s;
			else
				readerStatus[id] = s;
	        repaint();
   }

	void println(int s, int number, String st, int id)
	{
		        if(st.equals("w"))
		        {
				 	writerStatus[id] = s;
				}
				else
				{
					readerStatus[id] = s;
				}
		        repaint();
   }


    public void paint(Graphics g)
    {
        g.setFont(font);
        int xpos = 60;
        int ypos = 40;

		g.drawString("Status of Readers: ", 60, 20);
		g.drawString("Status of Writers: ", 360, 20);
		g.setFont(new Font("TimesRoman", 1, 14));

		/** print on canvas the status of writers and readers **/

		for(int i=1; i<=cn;i++)
		{
			g.setColor(Color.black);
			g.drawString("R" + i, xpos, ypos+(15*i+10*(i-1)));
			if(readerStatus[i] == 0)
			{
				g.setColor(Color.yellow);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));
			}
			else if (readerStatus[i] == 1)
			{
				g.setColor(Color.gray);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Want to read", xpos+120, ypos+(15*i + 10*(i-1)));
			}
			else if (readerStatus[i] == 3)
			{
				g.setColor(Color.gray);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));
			}
			else if (readerStatus[i] == 2)
			{
				g.setColor(Color.blue);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Reading...", xpos+120, ypos+(15*i + 10*(i-1)));
			}
		}
	 	xpos = 360;
	 	ypos = 40;
        for(int i=1; i<=pn; i++)
        {
			g.setColor(Color.black);
			g.drawString("W" + i, xpos, ypos+(15*i+10*(i-1)));
			if(writerStatus[i] == 0)
			{
				g.setColor(Color.yellow);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Sleeping ...", xpos+120, ypos+(15*i + 10*(i-1)));
			}
			else if (writerStatus[i] == 1)
			{
				g.setColor(Color.gray);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Waiting in the queue", xpos+120, ypos+(15*i + 10*(i-1)));
			}
			else if (writerStatus[i] == 2)
			{
				g.setColor(Color.blue);
				g.fillOval(xpos+60, ypos+(2*i+22*(i-1)), 18, 18);
				g.drawString("Writing ...", xpos+120, ypos+(15*i + 10*(i-1)));
			}

		}
    }
}

(4)

/*  File: Reader.java
 *  The reader will call the methods in DataBaseBuffer class to get the lock for reading.
 *  The last current readers will release the lock, and this activity is also controlled
 *  by the method in DataBaseBuffer class.
 *
 */

public class Reader extends Thread{
	private DataBaseBuffer buffer;
	private ReaderWriterApplet tapplet;
	private int cid;
	int delay  = 6500;
	int status = 0;

	public Reader(ReaderWriterApplet applet, DataBaseBuffer db, int id){
		buffer  = db;
		tapplet = applet;
		cid 	= id;
	}

	public void run(){
		while(true){
		 try{
			 status = 0;
			 tapplet.mc.println(status, "r", cid);
			 sleep((int) (Math.random()*delay));
			 buffer.acquireReadLock(tapplet, cid);
			 sleep((int) (Math.random()*delay));
			 buffer.releaseReadLock(tapplet, cid);
			} catch(InterruptedException e){
				System.err.println("Reader Execption " +  e.toString());
			}
		}
	}
}

(5)

/* File: ReaderWriterApplet.java
 *
 * This is a Java applet file for readers/writers problem animation. The GUI
 * of this applet contains three parts: animation canvas, message canvas
 * and a button panel.
 * The animation canvas is where the readers/writers animation is displayed.
 * The message canvas is where the statues of readers and writers are displayed.
 * The button panel has 6 basic buttons: START, STOP, PAUSE, CONTINUE, FASTER,
 * SLOWER. The user also can select the number of the readers and writers. Unless
 * the user selects different values, the default numbers of readers and writers are 2.
 * This applet also allows the user to choose from "Same Priority", "Readers have Priority"
 * and "Writers have Priority" three situations.
 *
 */

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.applet.Applet;
import java.lang.*;

public class ReaderWriterApplet extends Applet
{
	private ReaderWriterApplet applet = this;
	private DataBaseBuffer myBuffer;
	private int buffersize;

	private Button fastButton, slowButton, stopButton, startButton, pauseButton, continueButton;
	private Button stopReaderButton, stopWriterButton;
	private Panel buttonPanel, priorityPanel, namePanel;
	private Choice priority, reader, writer;
	private Thread at;
	private int readerN = 1;
	private int writerN = 1;

	boolean readerPriority = false;
	boolean writerPriority = false;
	boolean samePriority   = true; 	//default priority of readers and writers
	MessageCanvas mc;
	Reader[] r;
	Writer[] w;
	synchronized void startPushed() {notify();}
	synchronized void stopPushed() {notify();}

	public void init() {
		myBuffer = new DataBaseBuffer();
		mc = new MessageCanvas();
		resize(800, 600);
		setLayout(new GridLayout(3, 1));
		add(myBuffer);
		add(mc);

		buttonPanel = new Panel();
		priorityPanel = new Panel();
		namePanel = new Panel();
		Panel bPanel = new Panel(); 	// to hold all buttons and the labels
		bPanel.setFont(new Font("TimesRoman", Font.BOLD, 14));
		bPanel.setLayout(new GridLayout(3, 1));

		buttonPanel.add(startButton 	= new Button("START"));
		buttonPanel.add(stopButton 		= new Button("STOP"));
		buttonPanel.add(pauseButton 	= new Button("PAUSE"));
		buttonPanel.add(continueButton 	= new Button("CONTINUE"));
		buttonPanel.add(fastButton 		= new Button("FASTER"));
		buttonPanel.add(slowButton 		= new Button("SLOWER"));

		Panel choicePanel = new Panel();    //to hold all the choice boxes

		priority = new Choice();
		priority.addItem("Same Priority");
		priority.addItem("Writers Have Priority");
		priority.addItem("Readers Have Priority");
		priority.select("Same Priority");

		Label priorityLabel = new Label("Priority", 2);
		priorityLabel.setBackground(Color.lightGray);

		priorityPanel.add(priorityLabel);
		priorityPanel.add(priority);
		choicePanel.add(priorityPanel);

		reader = new Choice();
		for(int i = 0; i <=5; i++)
		{
			reader.addItem(Integer.toString(i));
		}
		reader.select("1");
		Label readerLabel = new Label("Number of Readers", 2);
		readerLabel.setBackground(Color.lightGray);
		Panel readerPanel = new Panel();
		readerPanel.add(readerLabel);
		readerPanel.add(reader);

		writer = new Choice();

		for(int i = 0; i<=5; i++)
		{
			writer.addItem(Integer.toString(i));
		}
		writer.select("1");
		Label writerLabel = new Label("Number of Writers", 2);
		writerLabel.setBackground(Color.lightGray);
		Panel writerPanel = new Panel();
		writerPanel.add(writerLabel);
		writerPanel.add(writer);

		Label nameLabel = new Label("Readers/Writers Animation");
		nameLabel.setFont(new Font("TimesRoman", Font.BOLD, 18));
		nameLabel.setForeground(Color.blue);
		namePanel.add(nameLabel);
		choicePanel.add(readerPanel);
		choicePanel.add(writerPanel);
		bPanel.add(choicePanel);
		bPanel.add(buttonPanel);
		bPanel.add(namePanel);
		add(bPanel);
	}

	public boolean action(Event evt, Object arg)
	{
		if(evt.target == priority)
		{
			if(arg.equals("Writers Have Priority"))
			{
				writerPriority = true;
				readerPriority = false;
				samePriority   = false;
			}
			else if(arg.equals("Readers Have Priority"))
			{
				readerPriority = true;
				writerPriority = false;
				samePriority   = false;
			}
			else
			{
				readerPriority = false;
				writerPriority = false;
				samePriority   = false;
			}
			return true;
		}
		else if(evt.target == reader)
		{
			readerN = Integer.parseInt(arg.toString());
			return true;
		}
		else if(evt.target == writer)
		{
			writerN = Integer.parseInt(arg.toString());
			return true;
		}
		else if(arg.equals("FASTER"))
		{
			int newDelay;
			if(readerN != 0)      newDelay = r[1].delay;
			else 				  newDelay = w[1].delay;

			newDelay /= 2;
			newDelay = newDelay < 100 ? 100: newDelay;

			for(int i = 1; i <= readerN; i++)
			{
					r[i].delay = newDelay;
			}
			for(int i = 1; i <= writerN; i++)
			{
					w[i].delay = newDelay;
			}
			return true;
		}
		else if(arg.equals("SLOWER"))
		{
			int newDelay;
			if(readerN !=0)       newDelay = w[1].delay;
			else 				  newDelay = r[1].delay;
			newDelay *= 2;
			for(int i = 1; i <= readerN; i++)
			{
				r[i].delay = newDelay;
			}
			for(int i = 1; i <= writerN; i++)
			{
				w[i].delay = newDelay;
			}
			return true;
		}
		else if(arg.equals("PAUSE"))
		{
			for(int i = 1; i <= readerN; i++)
			{
					r[i].suspend();
			}
			for(int i = 1; i <= writerN; i++)
			{
				w[i].suspend();
			}
			fastButton.setEnabled(false);
			slowButton.setEnabled(false);
			return true;
		}
		else if(arg.equals("CONTINUE"))
		{
			for(int i = 1; i <= readerN; i++)
			{
				if(r[i].isAlive()) 	r[i].resume();
			}
			for(int i = 1; i <= writerN; i++)
			{
				if(w[i].isAlive()) 	w[i].resume();
			}
			fastButton.setEnabled(true);
			slowButton.setEnabled(true);
			return true;
		}
		else if(arg.equals("START"))
		{
			r = new Reader[readerN+1];		//Reader[0] is a dummy slot
			w = new Writer[writerN+1];
			System.out.println("readers: "+readerN+" writers: " + writerN);
			mc.setMessage(writerN, readerN);
			myBuffer.setSize(readerN, writerN);
			for(int i = 1; i <= readerN; i++)
			{
				r[i] = new Reader(applet, myBuffer, i);
			}

			for(int i = 1; i <= writerN; i++)
			{
				w[i] = new Writer(applet, myBuffer, i);
			}
			for(int i = 1; i <= writerN; i++)
			{
				w[i].start();
			}
			for(int i = 1; i <= readerN; i++)
			{
				r[i].start();
			}
			fastButton.setEnabled(true);
			slowButton.setEnabled(true);
			startButton.setEnabled(false);
			reader.setEnabled(false);
			writer.setEnabled(false);
			priority.setEnabled(false);
			applet.startPushed();
			return true;
		}
		else if(arg.equals("STOP"))
		{
			for(int i = 1; i <= readerN; i++)
			{
				if(r[i].isAlive())
					r[i].stop();
				r[i] = null;
			}
			for(int i = 1; i <= writerN; i++)
			{
				if(w[i].isAlive())
					w[i].stop();
				 w[i] = null;
			}

			applet.stopPushed();
			startButton.setEnabled(true);
			fastButton.setEnabled(true);
			slowButton.setEnabled(true);
			reader.setEnabled(true);
			writer.setEnabled(true);
			priority.setEnabled(true);

			if(at != null) at.stop();
			at = null;
			return true;
		}
		else{ return false;}
	}
}

(6)

/*  File: Writer.java
 *
 *  The Writer will try to acquire the lock to access the shared data. It will return the lock
 *  after finish the writing.
 *
 */

public class Writer extends Thread{
	private DataBaseBuffer buffer;
	private ReaderWriterApplet tapplet;
	private int id;
	int delay  = 6500;
	int status = 0;

	public Writer(ReaderWriterApplet applet, DataBaseBuffer db, int id){
		buffer = db;
		tapplet = applet;
		this.id = id;
	}

	public void run(){
		while(true){
			try{
				status = 0;
				tapplet.mc.println(status, "w", id);
				sleep((int)(Math.random()*delay));
				buffer.acquireWriteLock(tapplet, id);
			   	sleep((int) (Math.random()*delay));
				buffer.releaseWriteLock(tapplet, id);
			} catch(InterruptedException e){
				System.err.println("Execption " +  e.toString());
			}
		}
	}
}
<!DOCTYPE HTML><HTML><HEAD></HEAD><BODY>
<APPLET CODE="ReaderWriterApplet.class" CODEBASE="." WIDTH=800 HEIGHT=550></APPLET>
</BODY></HTML>


 

四、调用

新建文件夹内完成如上的代码之后

在cmd内使用 appletviewer 即可

 

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
Java实现读者-写者问题的写者优先算法可以通过使用ReentrantReadWriteLock类来实现。该类提供了读写锁定的机制,其中读锁定可以被多个线程同时持有,而写锁定只能被单个线程持有。 下面是一个示例代码实现了读者-写者问题的写者优先算法: ``` import java.util.concurrent.locks.ReentrantReadWriteLock; public class WriterPriorityReadWriteLock { private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock(); private int readers = 0; private int writers = 0; private int writeRequests = 0; public void startRead() throws InterruptedException { readLock.lock(); try { while (writers > 0 || writeRequests > 0) { wait(); } readers++; } finally { readLock.unlock(); } } public void endRead() { readLock.lock(); try { readers--; notifyAll(); } finally { readLock.unlock(); } } public void startWrite() throws InterruptedException { writeLock.lock(); try { writeRequests++; while (readers > 0 || writers > 0) { wait(); } writeRequests--; writers++; } finally { writeLock.unlock(); } } public void endWrite() { writeLock.lock(); try { writers--; notifyAll(); } finally { writeLock.unlock(); } } } ``` 在这个实现中,读者和写者线程都可以通过调用startRead()和startWrite()方法来获取锁定,然后通过调用endRead()和endWrite()方法来释放锁定。在写者优先算法中,如果存在等待的写者,则新的读者线程必须等待所有等待的写者完成。 需要注意的是,如果有多个写者在等待锁定,则它们将按照先来先服务的顺序获得锁定。因此,这种实现可能会导致饥饿现象,即某些线程可能会无限期地等待。为了避免这种情况,可以采用其他的算法,例如读者优先算法或者公平算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傻根根呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值