📢博客主页:🏀九九舅舅酒酒🏀
📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论!👏
📢本文由 【九九舅舅酒酒】 原创,首发于 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 即可