`

生产者-消费者问题

阅读更多

<!-- [if gte mso 9]><xml><w:WordDocument><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery><w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery><w:DocumentKind>DocumentNotSpecified</w:DocumentKind><w:DrawingGridVerticalSpacing>7.8</w:DrawingGridVerticalSpacing><w:View>Normal</w:View><w:Compatibility></w:Compatibility><w:Zoom>0</w:Zoom></w:WordDocument></xml><![endif]-->

多进程/ 线程编程:生产者 - 消费者问题。( 1 人)                      

设置两类进程/ 线程,一类为生产者,一类为消费者;

建立缓冲区的数据结构;

随机启动生产者或消费者;

显示缓冲区状况;

随着进程/ 线程每次操作缓冲区,更新显示;

 

package ProducerAndConsumer;

import java.util.ArrayList ;
import java.util.List ;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestProducerConsumer extends JFrame {
	
	//窗体属性
	public static final int WIDTH =600 ;
	public static final int HEIGHT = 600 ;


	private JPanel pane1 ;
	private JPanel pane2 ;
	

	
	public static JTextArea textArea ;
	public static JTextField textBox ;   //手动设置缓冲区最大值
	public static JScrollPane scrollPane ;
	public JProgressBar progressBar = new JProgressBar() ;  //用进度条表示缓冲区存放产品情况

	Queue q = new Queue() ;     //创建一个消息队列对象
	private Thread threadWQ ;   //生产者线程
	private Thread threadRQ ;   //消费者线程
	Producer WQ = new Producer(q) ;
	Consumer RQ = new Consumer(q) ;
	
	
	
	public TestProducerConsumer(){
		
		pane1 = new JPanel() ;
		pane2 = new JPanel() ;
		
		setSize(WIDTH,HEIGHT) ;
		
		Toolkit too = Toolkit.getDefaultToolkit() ;
		Dimension screen = too.getScreenSize() ;
		int X = (screen.width-WIDTH)/2 ;
		int Y = (screen.height-HEIGHT)/2 ;
		setLocation(X,Y) ;
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;
		//this.setVisible(true) ;
	 
		layoutPane1() ;
		layoutPane2() ;
		
		setLayout(new BorderLayout()) ;
		add(pane1,BorderLayout.SOUTH) ;
		add(pane2,BorderLayout.NORTH) ;
	}
	
	public void layoutPane2(){
		
		JButton b1 = new JButton("开始模拟") ;
		JButton b2 = new JButton("暂停模拟") ;
		JButton b3 = new JButton("恢复运行") ;
		JButton b4 = new JButton("停止模拟") ;
		JButton b5 = new JButton("暂停生产") ;
		JButton b6 = new JButton("暂停消费") ;
		JButton b7 = new JButton("恢复消费") ;
		JButton b8 = new JButton("恢复生产") ;
		JButton b9 = new JButton("关闭") ;
		
		textBox = new JTextField("9",2) ;
		
		b1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				
				threadWQ = new Thread(WQ,"Thread-WQ1") ;
				
				threadRQ = new Thread(RQ,"Thread-RQ1") ;
				
				q.maxMessageNum = Integer.parseInt(textBox.getText()) ;
				
				progressBar.setMaximum(q.maxMessageNum) ;
				
				threadWQ.start() ;   //开始模拟
				threadRQ.start() ;
				textArea.append("所有线程已开始运行" + "\n") ;
			}
		}) ;
		
		b2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				threadWQ.suspend() ;
				threadRQ.suspend() ;
				textArea.append("已暂停模拟" + "\n") ;
			}
		}) ;
		
		b3.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("正在恢复..." + "\n") ;
				threadWQ.resume() ;
				threadRQ.resume() ;
				textArea.append("已恢复\n") ;
			}
		}) ;
		b4.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("停止模拟中..." + "\n") ;
				threadWQ.stop() ;
				threadRQ.stop() ;
				textArea.append("所有线程已停止" + "\n") ;
			}
		}) ;
		b5.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("正在暂停生产...\n") ;
				threadWQ.suspend() ;
				textArea.append("已暂停生产\n") ;
			}
		}) ;
		b6.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("正在暂停消费...\n") ;
				threadRQ.suspend() ;
				textArea.append("已暂停消费\n") ;
			}
		}) ;
		b7.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("正在恢复消费...\n") ;
				threadRQ.resume()  ;
				textArea.append("已恢复消费\n") ;
			}
		}) ;
		b8.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("正在恢复生产...\n") ;
				threadWQ.resume() ;
				textArea.append("已恢复生产\n") ;
			}
		}) ;
		b9.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				textArea.append("关闭中...") ;
				System.exit(0) ;
			}
		}) ;
		
		pane1.setLayout(new GridLayout(4,3)) ;
		pane1.add(textBox) ;
		pane1.add(b1) ;
		pane1.add(b4) ;
		pane1.add(b5) ;
		pane1.add(b8) ;
		pane1.add(b6) ;
		pane1.add(b7) ;
		pane1.add(b2) ;
		pane1.add(b3) ;
		pane1.add(b9) ; 
		
	}
	
	public void layoutPane1()
	{
		textArea = new JTextArea(25,25) ;
		progressBar.setEnabled(true) ;
		textArea.append("\n请按开始按钮") ;
		textArea.setEditable(false) ;
		textArea.setBackground(Color.pink) ;
		scrollPane = new JScrollPane(textArea) ;
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED) ;
		pane1.setLayout(new BorderLayout()) ;
		pane2.add(scrollPane,BorderLayout.NORTH) ;
		pane2.add(progressBar,BorderLayout.SOUTH) ;
	}




	
	//定义一个接口
	interface putMSG
	{
		public void output(String msg, JTextArea textArea, JProgressBar progressBar) ;//更新生产消费情况
		public void buffer(JTextField num) ;//设置缓冲区最大值
	}
	

	//消息类,产品
	static class Message {
		
		public static int id ;   //序列号
		public String content ; //消息内容
		
		public String getContent(){
			return this.content ;
		}
		
		public void setContent(String content){
			this.content = content ;
		}
		
		public int getId(){
			return this.id ;
		}
		
		public void setId(int id){
			this.id = id ;
		}
		
	}

	
	
	//消息队列类
	class Queue implements putMSG {

		List<Message> queue = new ArrayList<Message>() ;

		int maxMessageNum ;    //缓冲区最大值
		
		public synchronized void produce(Message message)
		{  //生产产品,用synchronized关键字实现同步
			
			this.notifyAll() ;
			
			while(queue.size() == maxMessageNum){
				
				output(Thread.currentThread().getName() + "缓冲区已满,等待中...."
							,textArea,progressBar) ;
				try{
					this.wait() ;
				}catch(InterruptedException e){
					System.err.println("Interrupted") ;
				}
			}
			queue.add(message) ;
			
			output(Thread.currentThread().getName()+"生产"
				+message.getContent()+"...当前产品数量:" 
					+ getCount(),textArea,progressBar) ;
		}
		
		public synchronized void consume(){//消费
			
			this.notifyAll() ;
			
			while(queue.size() == 0){
				output(Thread.currentThread().getName() + "缓冲区已空,等待中...."
						,textArea,progressBar) ;
				try{
					output("等待生产...",textArea,progressBar) ;
					this.wait() ;
					//output("等待结束",textArea,progressBar) ;
				}catch(InterruptedException e){
					e.printStackTrace() ;
				}
			}
			
			Message message = queue.get(0) ;
			queue.remove(0) ;
			output(Thread.currentThread().getName() + "正在消费" + message.getContent() 
				+ "...当前产品数量:" + getCount(),textArea,progressBar) ;
		}
		
		public synchronized int getCount(){
			return queue.size() ;
		}
		
		public void buffer(JTextField num) {
			 
			this.maxMessageNum = Integer.parseInt(num.getText()) ;
		}

		
		public void output(String msg, JTextArea textArea, JProgressBar progressBar) {
			 
			textArea.append(msg+"\n") ;
			textArea.append("当前容量:" + this.getCount() + "\n\n") ;
			progressBar.setValue(this.getCount()) ;
		}
	}
	
	
	
	
	
		//生产者类,继承Thread类
	class Producer extends Thread {

		private Queue queue ;
		
		Producer(Queue queue){
			this.queue = queue ;
		}
		
		public void run(){
			for(int i = 0; i < 100; i ++){   //生产者总共生产100个产品
				Message msg = new Message() ;
				msg.setId(++Message.id) ;
				msg.setContent("产品" + Message.id) ;
				queue.produce(msg) ;
				try{
					sleep(1000) ;
				}catch(InterruptedException e){
					System.out.println(e.getMessage()) ;
				}
			}
		}
	}
    
	//消费者类,继承Thread类
	class Consumer extends Thread {

		private Queue queue ;
		
		Consumer(Queue queue){
			this.queue = queue ;
		}
		
		public void run(){
			for(int i=0; i<100; i ++){
				queue.consume() ;
				try{
					sleep(2000) ;
				}catch(InterruptedException e){
					e.printStackTrace() ;
				}
			}
		}
	}
	
	
	
	public static void main(String[] args)
	{
		new TestProducerConsumer().setVisible(true) ;
	}
		

}


 
1
1
分享到:
评论

相关推荐

    利用记录型信号量解决生产者-消费者问题.doc

    记录型信号量通常用于解决生产者-消费者问题,因为它可以记录缓冲池中的空缓冲区和满缓冲区的数量,从而实现生产者和消费者的同步。 解决生产者-消费者问题的方法 为了解决生产者-消费者问题,我们可以使用记录型...

    用多线程同步方法解决生产者-消费者问题(操作系统课设

    生产者-消费者问题是操作系统中经典的问题之一,它是指在多线程环境下,多个生产者线程和消费者线程访问同一个共享缓冲区,导致缓冲区的数据混乱和不一致的问题。 在解决生产者-消费者问题时,需要使用同步机制来...

    用多进程同步方法解决生产者-消费者问题

    在生产者-消费者问题中,可以使用互斥量(mutex)保证缓冲区的独占访问,以及使用条件变量(condition variable)实现生产者等待消费者消费或消费者等待生产者生产。 4. **互斥量**:互斥量用于实现对共享资源的...

    生产者-消费者问题的模拟实现(课设含源代码).doc

    生产者-消费者问题是操作系统中经典的进程同步问题,它模拟了实际生产环境中的资源分配与消耗。在这个问题中,生产者进程负责生成数据并放入有限大小的缓冲区,而消费者进程则从缓冲区取出数据进行消费。为了确保...

    linux下用多进程同步方法解决生产者-消费者问题源代码

    生产者-消费者问题是计算机科学中的一个经典同步问题,主要探讨如何在多个进程中有效地共享有限的资源,以防止数据竞争和死锁的发生。在Linux操作系统环境下,这个问题通常通过信号量(semaphore)或管道(pipe)等...

    利用记录型信号量解决生产者-消费者问题

    1.利用记录型信号量解决生产者-消费者问题.odt1.利用记录型信号量解决生产者-消费者问题.odt1.利用记录型信号量解决生产者-消费者问题.odt

    以记录型信号量实现生产者-消费者问题

    以记录型信号量实现生产者-消费者问题 实验目的: 1.加深对进程同步概念的理解。 2.理解多道程序环境中,不同进程对资源访问及相互合作进程的关系的处理方法。 实验要求: 利用C语言程序模拟生产者-消费者问题和哲学...

    用多线程同步方法解决生产者-消费者问题(操作系统课设)

    ### 生产者-消费者问题详解 #### 一、问题背景与意义 生产者-消费者问题,作为操作系统领域经典的同步问题之一,广泛应用于多线程环境下资源共享的场景。它描述了一个或多个人(生产者)向一个有限容量的缓冲区中...

    jchc.rar_tearshmj_生产者_生产者-消费者问题 c++ _生产者和消费者_生产者消费者

    《生产者-消费者问题在C++中的实现》 生产者-消费者问题是多线程编程中的经典案例,它展示了如何在并发环境中实现线程间的同步与互斥。在本项目中,我们将探讨这个问题,并以C++语言为基础,创建一个在Windows 2000...

    用多线程同步方法解决生产者-消费者问题

    生产者-消费者问题是这种并发模型的一个经典案例,它涉及到如何在多个线程间共享资源,确保数据的一致性和正确性。在这个场景中,生产者线程负责生成数据并放入一个有限的缓冲区,而消费者线程则负责从缓冲区取出...

    进程同步与互斥 生产者与消费者问题--操作系统大作业

    生产者-消费者问题是一个经典的进程同步问题,涉及到两个进程(或线程)——生产者和消费者。生产者负责生产数据项并将其放入一个共享缓冲区,而消费者则从这个缓冲区中取出数据项进行处理。为了保证正确性,需要...

    生产者-消费者问题的Win32实现

    生产者-消费者问题是多线程编程中的一个经典同步问题,源于操作系统理论,旨在演示如何在多个线程之间安全地共享有限资源。在这个问题中,"生产者"线程负责生成数据,而"消费者"线程则负责处理这些数据。为了确保...

    pandc.rar_生产控制系统_生产者与消费者_生产者-消费者问题

    生产者-消费者问题的基本情景是这样的:一个系统中有两个角色,即生产者和消费者。生产者负责生成数据,而消费者则负责处理这些数据。在实际应用中,这可能意味着生产者在内存中创建数据结构(如队列),然后消费者...

    用多进程同步方法演示“生产者-消费者”问题

    1、设计目的:通过研究Linux的进程机制和信号量,实现生产者消费者问题的并发控制。 2、说明:有界缓冲区内设有20个存储单元,放入取出的产品设定为1-20个整数。 3、设计要求: 生产者和消费者进程的数目不固定,可...

    计算机课程设计 操作系统生产者-消费者问题

    该问题的提出是为了研究 Linux 的进程机制和信号量的实现生产者消费者问题的并发控制。通过研究该问题,可以深入了解操作系统的设计思想和实现方法。 生产者-消费者问题的定义 生产者-消费者问题是一种同步问题的...

    PC.rar_pv操作_生产者消费者_生产者-消费者问题

    首先,我们来看一下“生产者-消费者问题”的基本设定:一个系统中有两个角色,生产者和消费者。生产者负责生成数据,而消费者则负责消费这些数据。系统中有一个共享缓冲区,用于存储生产者产生的数据,供消费者取用...

    用信号量解决生产者-消费者问题.zip

    在 Ubuntu 下编写程序,用信号量解决生产者-消费者问题 在 Ubuntu 下编写应用程序 pc.c,解决经典的生产者-消费者问题,完成下面的功能: 建立一个生产者进程,N 个消费者进程(N &gt; 1) 用文件建立一个共享缓冲区 生产...

    生产者-消费者问题 VC++

    生产者-消费者问题是多线程编程中的一个经典案例,它主要展示了如何在多个并发执行的线程之间协调数据共享,确保资源的有效利用和系统稳定。在这个VC++实现的示例中,我们将深入探讨这个问题,以及如何使用C++的多...

    consumer_producer.rar_操作系统_生产 消费_生产者-消费者问题_进程调度

    在操作系统领域,生产者-消费者问题是多线程和进程同步的经典模型,用于描述并发执行的生产者进程与消费者进程如何共享资源而不会产生数据竞争或死锁的现象。在这个问题中,生产者负责生成数据,而消费者则负责消费...

Global site tag (gtag.js) - Google Analytics