`
mwei
  • 浏览: 123917 次
  • 性别: Icon_minigender_1
  • 来自: 抽象空间
社区版块
存档分类
最新评论

练习:生产者-消费者

    博客分类:
  • java
阅读更多
关于Object.wait()和Object.notify()/notifyAll()的使用,再写个练习。
生产者-消费者问题:有一个公共的资源池Source,生产者生产物品放到资源池中,消费者从资源池拿物品消费掉。
当资源池没有资源(物品)的时候,通知生产者生产物品放到资源池里;
当任何一个生产者生产完成之后,通知消费者们来消费物品;
消费者们会把所有资源消费掉,然后通知生产者生产物品;
啰嗦这么多,就是生产的时候只能有一个生产者,不能两个(多个)生产者连续生产;消费的时候可以有多个消费者连续消费。
就用这样的需求练习练习吧。
假设资源池Source是个长度为30的数组int[] source=new int[30]; //值[1,2,3...,28,29,30] 数组的值=相应下标+1;
数组的值只是用于标记,标记这个位置已经放置物品了;
第一次生产了20个物品,那么放置的位置是数组的下标[0,19],相应值是[1,20];
那么下次(可能是别的生产者)放置物品的开始位置(下标)是20;
通知消费者们来消费,那么消费者消费的开始位置(下标)是0;
消费完之后,如果第二次也生产了20个物品,那么放置的位置是数组的下标[20,9],相应值是[21,22..29,30,1,2...9,10];
那么下次(可能是别的生产者)放置物品的开始位置(下标)是10;通知消费者们来消费,那么消费者消费的开始位置(下标)是20;
此时把资源池想象成为一个可旋转的大圆桌,在圆桌的边缘放置了30个碟子,编号就是0到29;
通过向固定的方向旋转圆桌来有秩序的生产和消费^..^
还请JE上的朋友给点建议。
资源池类:
/**
 * 资源池
 * @author mwei
 * @version 1.0
 */
public class Source {
	public static final int CAPACITY=30;
	public static int[] source=new int[CAPACITY]; //值[1,2,3...,28,29,30]
	public static int in=0; //the position to set source
	public static int out=0; //the position to get source	
	public static final byte[] LOCK=new byte[0];
}

生产者类:
import java.util.Random;

public class Producer implements Runnable{
	public static Random random=new Random();
	public static volatile boolean prun=true; //信号量
	private String name;
	public Producer(String name){this.name=name;}
	public String getName(){return name;}
	public void run(){produce();}
	public void produce(){		
		while (true) {
			synchronized (Source.LOCK) {
				if (prun) {
					Source.LOCK.notifyAll();
					int planNum = random.nextInt(10) + 15; // 计划生产资源的数量,最少15个,最多24个
					int actualNum = 0;
					for (int i = Source.out; i < Source.CAPACITY + Source.out; i++) { // 查找放置资源的位置
						int index = i % Source.CAPACITY;
						if (Source.source[index] == 0) {
							Source.in = index; // 找到
							break;
						}
					}
					for (int i = 0; i < planNum; i++) { // 放置资源
						if (Source.source[Source.in] == 0) {
							actualNum++; // 统计实际放置资源的个数
							Source.source[Source.in] = Source.in + 1;
							Source.in = (++Source.in % Source.CAPACITY);
						}
					}
					int total = 0;
					for (int i = 0; i < Source.CAPACITY; i++) { // 统计资源池中总共的资源个数
						if (Source.source[i] != 0)
							total++;
					}
					System.out.print(this.getName() + "Plan : " + planNum
							+ "\t Produce : " + actualNum); // 输出计划量和实际生产量
					System.out.println("\tTotal : " + total + "\tRange : ["
							+ Source.out + ","
							+ (Source.in + Source.CAPACITY - 1)
							% Source.CAPACITY + "]"); // 资源总值及范围
					prun = false; // 生产者只生产一次
					Consumer.crun = true;
				} else {
					try {
						System.out.println(this.getName() + ".wait();");
						Source.LOCK.wait();
					} catch (InterruptedException ie) {
						ie.printStackTrace();
					}
				}
			} // end syn
		} // end while
	}
}

消费者类
public class Consumer implements Runnable{
	public static final int CONSUME_NUM=4;
	public static volatile boolean crun=false; //信号量
	private String name;
	public Consumer(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	public void run(){
		consume();
	}
	public void consume(){
		while (true) {
			synchronized (Source.LOCK) {
				if (crun) {
					Source.LOCK.notifyAll();
					int actualNum = 0;
					for (int i = 0; i < CONSUME_NUM; i++) {
						if (Source.source[Source.out] != 0) {
							actualNum++;
							Source.source[Source.out] = 0; // 消耗掉
							Source.out = (Source.out + 1) % Source.CAPACITY;
						} else {
							; // do nothing
						}
					}
					System.out.println(this.getName() + " : consumes "
							+ actualNum);
					int total = 0;
					for (int i = 0; i < Source.CAPACITY; i++) { // 统计资源池中总共的资源个数
						if (Source.source[i] != 0)
							total++;
					}
					if (total == 0) { // 消费者把资源消费光了再通知生产者
						crun = false;
						Producer.prun = true;
					}
				} else {
					try {
						System.out.println(this.getName() + ".wait();");
						Source.LOCK.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} // end syn
		} // end while
	}
}

测试:
/**
 * test 3 producers and 4 consumers
 * @author mwei
 */
public class Test {	
	public static void main(String[] args) {
		new Thread(new Producer("P1=>")).start();
		new Thread(new Producer("P2=>")).start();
		new Thread(new Producer("P3=>")).start();
		new Thread(new Consumer("C1=>")).start();
		new Thread(new Consumer("C2=>")).start();
		new Thread(new Consumer("C3=>")).start();
		new Thread(new Consumer("C4=>")).start();		

	}
}

运行结果的一部分:
P3=>Plan : 18	 Produce : 18	Total : 18	Range : [28,15]
C2=> : consumes 4
C3=> : consumes 4
C1=> : consumes 4
C4=> : consumes 4
P3=>.wait();
C2=> : consumes 2
P2=>Plan : 19	 Produce : 19	Total : 19	Range : [16,4]
C3=> : consumes 4
C1=> : consumes 4
C4=> : consumes 4
C2=> : consumes 4
P2=>.wait();
C3=> : consumes 3
C1=>.wait();
C4=>.wait();
C2=>.wait();
C3=>.wait();
P3=>Plan : 18	 Produce : 18	Total : 18	Range : [5,22]
P1=>.wait();
P2=>.wait();
C3=> : consumes 4
C1=> : consumes 4
P3=>.wait();
C4=> : consumes 4
C2=> : consumes 4
C3=> : consumes 2
C1=>.wait();
C4=>.wait();
C2=>.wait();
C3=>.wait();
P2=>Plan : 18	 Produce : 18	Total : 18	Range : [23,10]
P1=>.wait();
P3=>.wait();
P2=>.wait();
C1=> : consumes 4
C4=> : consumes 4
C3=> : consumes 4
C2=> : consumes 4
C1=> : consumes 2
C4=>.wait();
C3=>.wait();
C2=>.wait();



分享到:
评论

相关推荐

    QT/C++多线程练习:单生产者多消费者(源码)

    主线程、生产者线程(一)、消费者管理线程(一)、消费者线程(多),以及一些全局变量。 主线程职责:UI控件的控制和显示、控制生产者:调节生产的速度和暂停与继续、控制消费 生产者线程职责:根据商品数量调控...

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

    在操作系统领域,生产者-消费者问题是经典的问题之一,它涉及到多线程同步和资源管理。本项目通过使用多线程同步方法解决这个问题,具体表现为有界缓冲区的管理,其中包含20个存储单元,存储1~20的整型数。下面是...

    Qt入门练习项目——生产者消费者模型.zip

    **Qt入门练习项目——生产者消费者模型** 在编程领域,生产者消费者模型是一种常见的多线程同步问题的解决方案。这个模型通常用于处理数据流的异步处理,其中一个或多个线程(生产者)生成数据,而其他线程(消费者...

    操作系统生产者和消费者问题

    在生产者-消费者模型中,有两个主要的角色:生产者和消费者。生产者负责创建或生成数据,而消费者则负责消费这些数据。共享的资源通常是一个缓冲区,生产者将数据放入缓冲区,消费者从中取出数据。问题的关键在于...

    操作系统上机实验报告 进程同步和通信-生产者和消费者问题模拟

    ### 操作系统上机实验报告:进程同步和通信——生产者和消费者问题模拟 #### 一、实验目的 本次实验的主要目的是让学生通过调试、修改、运行一个模拟程序,加深对进程概念的理解,熟悉同步和通信的过程,掌握进程...

    Visual studio 2008做的生产者消费者操作系统练习

    在这个练习中,文件"P_C"可能包含了具体的源代码实现,包括生产者类和消费者类的定义,以及主程序中创建线程、启动生产者和消费者、以及必要的同步操作。通过分析和理解这段代码,可以深入学习多线程编程、同步原语...

    并行openmp程序实现生产者消费者

    在"并行openmp程序生产者消费者-渠涧涛-104753130775"这个文件中,可能包含了渠涧涛同学完成的源代码和相关分析。通过阅读和理解这份代码,我们可以更深入地了解如何在OpenMP环境中实现生产者消费者模式,包括线程的...

    操作系统课程设计生产者与消费者

    “生产者-消费者”问题通常被描述为:存在一个固定大小的缓冲区,多个生产者进程不断产生数据并将数据放入缓冲区,而多个消费者进程则不断地从缓冲区取出数据进行处理。为了保证数据的一致性和完整性,需要解决两个...

    操作系统实验指导书(全)

    - 实现生产者消费者模型中的同步问题。 **实验内容:** - 使用信号量机制实现生产者和消费者的同步。 - 设计并实现相应的算法以解决资源竞争问题。 #### 实验五:作业调度实验 **实验目的:** - 理解作业调度的...

    操作系统中生产者与消费者问题实例

    操作系统中的生产者与消费者问题是多线程编程中的一个经典模型,它主要研究的是如何有效地在共享资源之间协调生产者和消费者的行为,以避免数据竞争和死锁等问题。在这个C#编写的实例中,我们将深入探讨这个问题及其...

    经济法理论实务练习题.doc

    - **选项B** 这种情况构成了产品缺陷,生产者和销售者需要承担相应的法律责任。 34. **有限责任的含义:** - **选项D** 有限责任指的是股东以其出资额为限对公司承担责任,超出部分由公司独立承担。 35. **在...

    java生产者消费者模型

    5. **设计模式**:生产者消费者模型可以看作是一种“生产者-消费者”设计模式的实例,它属于行为设计模式,用于协调异步处理和共享资源。此外,还可以结合观察者模式,让消费者订阅生产者,当有新数据时,生产者通知...

    消费者生产者程序 1到100间 按顺序 进,乱序有规律出

    标题中的“消费者生产者程序”是指在多线程编程中的一种经典模式,也称为缓冲区模型。在这种模式中,一个线程(生产者)负责创建或生成数据,另一个线程(消费者)则负责处理这些数据。这个场景通常用于并发环境,以...

    java生产者消费者demo

    在Java编程中,"生产者消费者问题"是一个经典的多线程同步问题,它涉及到了如何在多线程环境下有效地共享资源。在这个问题中,"生产者"负责创建资源,而"消费者"则负责消费这些资源。为了确保生产者不会在资源耗尽时...

    practicas-Sistemas-concurrentes-y-distribuidos:格拉纳达大学并发与分布式系统实践课程集

    # 实践并发和分布式系统============================================== 格拉纳达大学并发和分布式系统实践的一套程序。... 生产者-消费者练习实践3: 生产者-消费者运动 (mpi) 哲学家练习哲学家侍者练习

    生产者消费者为模型的多线程编程c#原创

    在C#编程中,"生产者消费者模型"是一种常见的多线程设计模式,它通过分离数据的生产和消费过程,使得生产者线程可以专心于创建数据,而消费者线程则专注于处理这些数据,两者互不干扰,提高了系统效率。在这个模型中...

    2014高考生物一轮复习 课时跟踪检测(一)走近细胞配套练习 新人教版

    - ①②不一定是分解者,也可能作为生产者或消费者。 12. **显微镜观察细胞:** - 显微镜放大倍率增加可能导致视野变暗。 - 低倍镜下可见的细胞,高倍镜下不一定可见。 - 高倍镜下观察到的细胞数量减少。 以上...

    福建省南安市石井镇厚德中学九年级英语上册 Unit 2 Topic 2 All these problems are very

    - 世界上最大的煤炭生产国和消费国:the world's largest producer and consumer of coal - (作为)结果,因此:as a result, therefore - 一些有用的措施:some useful measures - (我们中)没有人:none of ...

Global site tag (gtag.js) - Google Analytics