⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 源代码producer_consumer.java

📁 操作系课程设计适用于本科大学生课程设计 希望大家相互帮助 一起加油
💻 JAVA
字号:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;

public class Producer_Consumer extends Applet implements ActionListener
{
     public static final int k=5;
     public static final int SPEED=5000;
     CBuffer   bBuf; 		  //the object of Buffer process
     CConsumer cCons;		  //the object of Consumer process
     CProducer pProd;		  //the object of Producer process这是三个进程,一定要注意,很关键
     
     
     Panel   pbutton;
     private Button bStart=new Button();
     private Button bPause=new Button();
     private Button bEnd=new Button();
     private Button bContinue=new Button();
     GridBagConstraints cons;

     CTrace1             trace1;
	 CTrace2             trace2;		//动画步骤
     CIntroCanvas        introduce;     //说明语句
     CProducerCanvas     pProdC;
     CConsumerCanvas     cConsC;
     CBufferCanvas       bBufC;//声明一些对象,在具体用时在进行创建

     public void init()
     {
	GridBagLayout layout=new GridBagLayout();//利用GridBagLayout布局管理器
	setLayout(layout);
	resize(500,500);//显示大小
	cons=new GridBagConstraints();
	cons.anchor=GridBagConstraints.CENTER;	
 	cons.weightx=300;
	cons.weighty=300;

	pbutton= new Panel(); //定义一个面板对象,所谓面板就是一种存放各种控件的容器罢了
	pbutton.resize(500,100);
	addButton(pbutton,bStart,"开始");
	addButton(pbutton,bPause,"暂停");
	addButton(pbutton,bContinue,"继续");
	addButton(pbutton,bEnd,"结束");//在面板上加在以上按钮
	addGrid(pbutton,cons,1,0,9,2);//addGrid函数在下面的代码中有定义	

	pProdC=new CProducerCanvas();
	addGrid(pProdC,cons,1,2,1,2);
	cConsC=new CConsumerCanvas();
	addGrid(cConsC,cons,10,2,1,2);//创建对象并放到屏幕上

	cons.anchor=GridBagConstraints.WEST;
	trace1 = new CTrace1();
	addGrid(trace1,cons,2,3,2,1);
	cons.anchor=GridBagConstraints.EAST;
	trace2 = new CTrace2();
	addGrid(trace2,cons,8,3,2,1);
	
	cons.anchor=GridBagConstraints.NORTH;
	bBufC=new CBufferCanvas(k);
	addGrid(bBufC,cons,2,3,7,1);
	cons.anchor=GridBagConstraints.NORTH;

	introduce=new CIntroCanvas();
	addGrid(introduce,cons,1,8,9,1);
	bBuf=new CBuffer(this,k);//以上代码实现了整个图形界面的布局,大家可以不必关心每一个函数的用法
   }

    public void addGrid(Component c,GridBagConstraints gc,int  x,
	int y,int dx,int dy) //在此定义addGrid 函数
       {
		gc.gridx=x;
		gc.gridy=y;
		gc.gridwidth=dx;
		gc.gridheight=dy;
		add(c,gc);//add是系统自带的函数,用于把控件放到指定的位子上
	}

	public void addButton(Container c,Button b,String s)	{
		b.setLabel(s);
		c.add(b);
		b.addActionListener(this);//监听事件的发生
	}

	public void actionPerformed(ActionEvent evt)//处理监听到的相应事件
	{
		Button b=(Button)evt.getSource();
		if(b==bStart)	{ 
			startp();//如果是开始按钮被按下,则执行startp()函数,
		}
		else if(b==bEnd)	{
 			pProd.stop();//结束按钮执行的代码
 			cCons.stop();
			bBuf.stop();
 			pProd=null;
			cCons=null;
		}
		else if(b==bPause)	{
			pProd.suspend();
			cCons.suspend();//停止按钮执行的相应函数
		}
		else if(b==bContinue)	{
			pProd.resume();
			cCons.resume();//继续按钮执行的相应函数
		}
	}

	public void startp()	{
		pProd = new CProducer(this);//在此定义startp()函数
		cCons = new CConsumer(this);
	    bBufC.reset();//reset()函数在相应的对象中有定义,大家可以查看一下相应类中的代码
		bBuf.reset();
		pProdC.reset();
		cConsC.reset();
		trace1.reset();
		trace2.reset();
		trace1.repaint();
		trace2.repaint();
	}   
	     
}

class CProducerCanvas extends Canvas//定义CProducerCanvas类,
{
	private boolean prod;    //prod:false-未生产,true-生产
	public CProducerCanvas()	{
		prod = false;  //此类的构造函数   
		resize(60,300);
	}
   
    public void reset()//在此定义Reset函数
	{
		prod=false;//首先置成未生产
		repaint();//重新执行paint函数,//在下面五行中有Paint函数的定义
	}
	
	synchronized public void update(boolean p){
		prod = p;
		repaint();
	}
 
    public void paint(Graphics g)	{
		g.drawString("生产者",10,20);
	   	if(prod)
		{   
		    g.setColor(Color.red);//对应左上角的小球,如果正在生产,则小球是红颜色的
	            g.fillOval(20,50,15,15);
		    prod = false;
		}
	}	
}

class CConsumerCanvas extends Canvas
{
	private boolean cons;    //cons:false-消费过了,true-要消费
	public CConsumerCanvas()	{//构造函数
		cons = false;     
		resize(60,300);
	}
	
	public void reset()//实现重置功能
	{
	    cons=false;//消费过了
		repaint();//重新执行下面的Paint()函数
	}

	synchronized public void update(boolean c){
		cons = c;
		repaint();
	}
 
    public void paint(Graphics g)	{
		g.drawString("消费者",10,20);
	   	if(cons)
		{   
		    g.setColor(Color.green);
	            g.fillOval(20,50,15,15);//对应右上角小球,如果要消费,则是绿颜色的.
		    cons = false;//
		}
	}	
}

class CBufferCanvas extends Canvas//缓冲区,即我们看到的中间那五个方格
{
	private int k,num;
	private boolean[] isFull;//定义一个布尔类型的数组,用于分别判断那五个缓冲区是否已经满了
	private boolean   CanPut,CanGet;//定义两个布尔型变量,分别用于判断缓冲区是否能够放或者取

	public CBufferCanvas(int k){
		resize(300,110);//构造函数
		this.k=k;
		isFull=new boolean[k];
		for(int i=0;i<k;i++) isFull[i]=false;//分别置成空
		num=-1;
		CanPut=false;
		CanGet=false;
	}

	public void reset()	{
		num=-1;
		CanPut=false;
		CanGet=false;
		for(int i=0;i<k;i++) isFull[i]=false;
		repaint();
	}

	public void canput()
	{
		CanPut=true;
		repaint();
	}		

    public void put()
    {
	
		num++;
		isFull[num]=true;
		repaint();
	}

    public void set_put()
	{
		CanPut=false;
		repaint();
	}

	public void get()
	{
		isFull[num]=false;
		num--;
		CanGet=true;
		repaint();
	}

    public void set_get()
	{
		CanGet=false;
		repaint();
	}
	public void paint(Graphics g) 	{//真正要执行的部分
		for(int n=0;n<k;n++)	{
			g.setColor(Color.black);
			g.drawRect(40*n+50,60,40,35);//画矩形,Black为所用的颜色
			if(isFull[n])	{
				g.setColor(Color.green);
				g.fillRect(40*n+51,61,39,34);//填充矩形,Green为所用的颜色
			}
		}
		if (CanPut)
		{
			g.setColor(Color.black);
			g.drawLine(50,60,40,50);
			g.drawLine(50,95,40,105);
		}
		else if (CanGet)
		{
			g.setColor(Color.black);
			g.drawLine(40*(k-1)+90,60,40*(k-1)+100,50);
			g.drawLine(40*(k-1)+90,95,40*(k-1)+100,105);
		}
	}
	
}

class CBuffer extends Thread  //是一个进程,本例中一共有三个.
{
	private int k,num;
	private boolean[] isFull;
	private boolean   CanPut,CanGet;	

    Producer_Consumer ps;//声明一个Producer_Consumer对象,

	public CBuffer(Producer_Consumer ps,int k){  //是一个构造含数,注意其中的两小参数
		this.k=k;//第一个K是上面定义的私有变量,第二个K是此构造函数的参数
		isFull=new boolean[k];
		for(int i=0;i<k;i++) isFull[i]=false;
		num=-1;
		CanPut=false;
		CanGet=false;
 
 		this.ps=ps;
	}

	public void reset()	{
		num=-1;
		CanPut=false;
		CanGet=false;
		for(int i=0;i<k;i++) isFull[i]=false;
	}

	public synchronized void put()
	{
		while (num+1==k){//如果缓冲区已满,则执行Set_put函数,
		    ps.bBufC.set_put();
			try{
				wait();//因为满了嘛,所以要等有空位子了
			}
			catch(InterruptedException e){}//Try,Catch是Java中的异常与捕获,这里大家可以不必了解
		}
		isFull[++num]=true;//如果没有满,则执行以下的代码

		CanPut=true;
		ps.bBufC.canput();
		ps.trace1.go();
		ps.bBufC.put();
		notify();
		try{
				Thread.sleep(500);//500为时间量
			}catch(InterruptedException e){}
		ps.pProdC.reset();
		ps.bBufC.set_put();
	}		

	public synchronized void get()
	{

		while (num==-1)//如果缓冲区空了,则执行下面的语句
		{
		    ps.bBufC.set_get();//不可取了
			try{
				wait();//要等待了,直到有东西可取
			}
			catch(InterruptedException e){}//在此期间,当系统出现中断时的处理
		}
		isFull[num--]=false;//如果不空,则执行以下语句
		CanGet=true;
		ps.bBufC.get();
		ps.trace2.go();
		notify();//?
		try{
				Thread.sleep(500);
			}catch(InterruptedException e){}
		ps.cConsC.reset();
		ps.bBufC.set_get();
	}

	public void run(){
		while (true)
		{
			try{
				Thread.sleep((int)(Math.random()*5000));
			}
			catch (InterruptedException e){}
		}
	}
	
}

class CTrace1 extends Canvas
{
	public int p,pend=23;  //p:初始位置;endp:共多少次画面

	public CTrace1(){	
		p=-1;
		resize(100,50);	
	}	

	public void go(){
		p=0;
		while(p<pend)	{
			try		{	Thread.sleep(50); //估计是50毫秒,我们可以看到小球的轨迹	
			} catch(InterruptedException ex){}
			repaint();
			p++;		
		}
	}

	public void reset()	{p=-1;}//置回初始位置
	
	public void paint(Graphics g)	{
		if((p<(pend-1))&&(p>=0))   {
			g.setColor(Color.red);
			g.fillOval(p*2,10,12,12);//可以看到由于P*2,才使小球有了轨迹
		}
	}
}


class CTrace2 extends Canvas//与CTrace1原理是一样的
{
	public int p,pend=23;  //p:初始位置;endp:共多少次画面

	public CTrace2(){	
		p=-1;
		resize(100,50);	
	}	

	public void go(){
		p=0;
		while(p<pend)	{
			try		{	Thread.sleep(50); 	
			} catch(InterruptedException ex){}
			repaint();
			p++;		
		}
	}

	public void reset()	{p=-1;}

	public void paint(Graphics g)	{
		if((p<(pend-1))&&(p>=0))   {
			g.setColor(Color.green);
			g.fillOval(p*2,10,12,12);
		}
	}
}

class CIntroCanvas extends Canvas	{//是一块提示画布
	private String s0,s1,s2,s3,s4,s5,s6,s7,s8;
	
	public CIntroCanvas()	{
		resize(300,145);
		s0="生产者-消费者问题例示:";
		s1="生产者生产一个物品,放到BUFFER中;";
		s2="消费者需要消费,也从BUFFER中取。";
		s3="生产者生产一个物品后,其下方有红灯表示。";
		s4="消费者要消费时,提出请求,其下方有绿灯表示。";
		s5="当缓冲区控制台发现可以让生产者放置物品时,";
		s6="对应着生产者的Buffer门打开。";
		s7="当缓冲区控制台发现可以让消费者取物品时,";
		s8="对应着消费者的Buffer门打开。";
	}
	public void paint(Graphics g)	{
	  g.drawString(s0,0,10);//位置罢了
	  g.drawString(s1,10,25);
	  g.drawString(s2,10,40);
	  g.drawString(s3,10,55);
	  g.drawString(s4,10,70);
	  g.drawString(s5,10,85);
	  g.drawString(s6,10,100);
	  g.drawString(s7,10,115);
	  g.drawString(s8,10,130);
	}
}

class CConsumer extends Thread //消费者的进程
{
	Producer_Consumer pc;
	
	public CConsumer(Producer_Consumer pc)//构造函数,注意其中的参数
	{
		this.pc=pc;
		pc.cConsC.update(false);//消费过了,Update函数可以在Producer_Csonsumer类中查到
		this.start();           //
	}

	public void run()
	{	
		while (true)
		{
			pc.cConsC.update(true);	//要消费		
			pc.bBuf.get();//从缓冲区中取东西了
			try{
				Thread.sleep((int)(Math.random()*Producer_Consumer.SPEED));
			}catch(InterruptedException e){}//这里对应着加速消费速度按钮和减慢减慢消费速度按钮
		}
	}
}

class CProducer extends Thread//生产者的进程
{
	Producer_Consumer pc;
	
	public CProducer(Producer_Consumer pc)//构造函数
	{
		this.pc = pc;
		pc.pProdC.update(false);
		this.start();
	}
	
	public void run()
	{
		while(true)
		{
			pc.pProdC.update(true);//要生产了
			pc.bBuf.put();//把生产的东西放到缓冲区中
			try{
				Thread.sleep((int)(Math.random()*Producer_Consumer.SPEED));
			}catch(InterruptedException e){}//这里对应着加快生产速度按钮和减慢生产速度按钮
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -