在操作系统课程设计中,老师给了这样一个题目,并且要求以GUI的形式模拟整个操作过程。所以,首先映入我脑海的语言便是JAVA。主意敲定,开始构思,如何用JAVA来巧妙地表现这种机制,尽管Java提供了synchronized,Semaphore等关键词,但在构思过程中依然是困难的。
建立读者类和写者类,建立之后为了实现写者优先需设定五个信号量,然而这五个信号量是在两个类中交替出现的,而且要保证原子性。不得已将这五个类全部放在主类中,设为静态变量。由此在另外两个类应用时很繁琐。
五个信号量:
public static Semaphore readCountSemaphore=new Semaphore(1); //读者数量更改,保持原子性
public static Semaphore writeSemaphore=new Semaphore(1); //写者信号量
public static Semaphore reader_wait=new Semaphore(1); //读者信号量
public static Semaphore first_reader_wait=new Semaphore(1);//第一个读者,为了实现写者优先
public static Semaphore writerCountSemaphore=new Semaphore(1);//写者数量更改,保持原子性
完整代码:
package com;
import java.awt.BorderLayout;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.Semaphore;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class ReadAndWrite extends JFrame
{
public static int countReader; //手动设置读者数
public static int countWriter; //手动设置写者数
public static int readCount=0; //等待读者数量
public static int writeCount=0; //等待写者数量
public static Semaphore readCountSemaphore=new Semaphore(1); //读者数量更改,保持原子性
public static Semaphore writeSemaphore=new Semaphore(1); //写者信号量
public static Semaphore reader_wait=new Semaphore(1); //读者信号量
public static Semaphore first_reader_wait=new Semaphore(1);//第一个读者,为了实现写者优先
public static Semaphore writerCountSemaphore=new Semaphore(1);//写者数量更改,保持原子性
//GUI
static JTextField textfield1, textfield2, textfield3,textfield4;
JPanel panel, panel1, panel2;
JLabel label1, label2, label3, label4;
static JTextPane textpane;
public ReadAndWrite(){
Scanner sc = new Scanner(System.in);//用来输入读写者个数
System.out.println("读者个数:");
countReader = sc.nextInt();
System.out.println("写者个数:");
countWriter = sc.nextInt();
textpane = new JTextPane();//动态执行界面
label1 = new JLabel("书:");
label2 = new JLabel("等待读者个数:");
label3 = new JLabel("等待写者个数:");
textfield1 = new JTextField(10);//显示谁正在对数据操作
textfield2 = new JTextField(10);//显示剩余读者个数
textfield3 = new JTextField(10);//显示剩余写者个数
panel1 = new JPanel();
panel1.add(label1);
panel1.add(textfield1);
panel1.add(label2);
panel1.add(textfield2);
panel1.add(label3);
panel1.add(textfield3);
JLabel label4 = new JLabel("正在等待读写者:");
textfield4 = new JTextField(44);//显示读写者的先后顺序
panel2 = new JPanel();
panel2.add(label4);
panel2.add(textfield4);
panel = new JPanel(new BorderLayout());
panel.add(panel1,BorderLayout.NORTH);
panel.add(panel2,BorderLayout.SOUTH);
panel.add(new JScrollPane(textpane),BorderLayout.CENTER);
setTitle("读写者问题");//将此窗体的标题设置为指定的字符串
setBounds(300, 300, 600, 400);
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
}
public static void insert(String str)//向textpane中插入动态信息
{
SimpleAttributeSet set = new SimpleAttributeSet();
StyleConstants.setUnderline(set, true);
try
{
textpane.getDocument().insertString(textpane.getDocument().getLength(), str + "\n", set);
}
catch (BadLocationException e)
{
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
ReadAndWrite raw = new ReadAndWrite();
int i = 1;
int j = 1;
while(i<=ReadAndWrite.countReader||j<=ReadAndWrite.countWriter){
if(new Random().nextBoolean()){ //随机判断读写者
if(i>ReadAndWrite.countReader)
continue;
ReadAndWrite.insert("读者R"+i+"来了");
raw.textfield4.setText(raw.textfield4.getText()+"R"+i+",");
new ReadThread(i);
i++;
}
else{
if(j>ReadAndWrite.countWriter)
continue;
ReadAndWrite.insert("读者W"+j+"来了");
raw.textfield4.setText(raw.textfield4.getText()+"W"+j+",");
new WriteThread(j);
j++;
}
}
}
}
读者类:
package com;
import java.util.Random;
//import java.util.concurrent.Semaphore;
public class ReadThread extends Thread
{
public int id;
public ReadThread(int id)
{
this.id = id;
this.start();
}
public void run()
{
try{
synchronized(this){
if(ReadAndWrite.writeSemaphore.availablePermits()>0)//判断是否有写者正在操作
ReadAndWrite.insert("读者R"+id+"可以读");
else
ReadAndWrite.insert("有写者在写操作,读者R"+id+"等待读");
ReadAndWrite.reader_wait.acquire();//阻塞第一个之后的读者
ReadAndWrite.first_reader_wait.acquire();//第一个读者申请资源,为了写者优先
ReadAndWrite.readCountSemaphore.acquire();//保持writeCount的原子性
if(ReadAndWrite.readCount==0)
ReadAndWrite.writeSemaphore.acquire();
ReadAndWrite.readCount++;
ReadAndWrite.textfield2.setText(" "+ReadAndWrite.readCount);//GUI显示
ReadAndWrite.readCountSemaphore.release();
ReadAndWrite.first_reader_wait.release();
ReadAndWrite.reader_wait.release();
ReadAndWrite.insert("R"+id+"读文件");//GUI显示
ReadAndWrite.textfield1.setText("读者R"+id);
Thread.sleep((long) (new Random().nextFloat()*2000));
ReadAndWrite.insert("读者R"+id+"读完了");
ReadAndWrite.readCountSemaphore.acquire();
ReadAndWrite.readCount--;
ReadAndWrite.textfield2.setText(" "+ReadAndWrite.readCount);
if(ReadAndWrite.readCount==0)
ReadAndWrite.writeSemaphore.release();
ReadAndWrite.readCountSemaphore.release();
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
写者类:
package com;
import java.util.Random;
public class WriteThread extends Thread
{
public int id;
public WriteThread(int id)
{
this.id=id;
this.start();
}
public void run()
{
try{
synchronized(this){
if(ReadAndWrite.writeSemaphore.availablePermits()>0)//判断是否有写者正在操作
ReadAndWrite.insert("写者W"+this.id+"可以写");
else
ReadAndWrite.insert("写者W"+this.id+"不可以写");
ReadAndWrite.writerCountSemaphore.acquire();//保持writeCount的原子性
if(ReadAndWrite.writeCount==0)
ReadAndWrite.first_reader_wait.acquire(); //如果写者数量为0,第一个读者申请访问
ReadAndWrite.writeCount++;
ReadAndWrite.textfield3.setText(" "+ReadAndWrite.writeCount);//GUI显示
ReadAndWrite.writerCountSemaphore.release();
ReadAndWrite.writeSemaphore.acquire();//写者开始操作,与其他操作互斥
ReadAndWrite.insert("写者W"+this.id+"正在写");//GUI显示
ReadAndWrite.textfield1.setText("写者W"+id);
Thread.sleep((long) (new Random().nextFloat()*2000));
ReadAndWrite.insert("写者W"+this.id+"写完了");
ReadAndWrite.writeSemaphore.release();
ReadAndWrite.writerCountSemaphore.acquire();
ReadAndWrite.writeCount--;
ReadAndWrite.textfield3.setText(" "+ReadAndWrite.writeCount);
if(ReadAndWrite.writeCount==0)//如果写者数量为0,唤醒第一个等待的读者
ReadAndWrite.first_reader_wait.release();
ReadAndWrite.writerCountSemaphore.release();
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PS:这是第一次在CSDN记录我自己编程的过程,自知写的蹩脚的很,既然迈出了这一步,就等着接受唾沫。雄关漫道真如铁,走你!