java 模拟实现消费者和生产者问题

题目要求

用java代码模拟实现:一个人不断往箱子里放苹果,另一个人不断从箱子里取苹果,箱子只能放5个苹果,苹果数量无限。要求不使用java.util.concurrent包中的类。

思路

这道题主要考,java并发编程、Object.wai()、Object.notify()方法的使用、循环队列的使用

1.使用两个线程分别模拟放苹果和取苹果。

2.定义一个类放苹果,类里主要是对一个数组的封装

注意:

Object.wait()及Object.notify()方法的使用,下面是摘自JDK1.6文档

public final void wait()
                throws InterruptedException在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。
当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。 

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用: 

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
     }
 此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅 notify 方法。 

抛出:
IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。
notify
public final void notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。 

此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者: 

通过执行此对象的同步实例方法。
通过执行在此对象上进行同步的 synchronized 语句的正文。
对于 Class 类型的对象,可以通过执行该类的同步静态方法。
一次只能有一个线程拥有对象的监视器。 

个人的理解wait()方法即阻塞当前线程,释放锁,直到有人调用notify()或notifyAll()方法来唤醒。注意是对同一对象使用两个方法

notify()主要是唤醒当前对象阻塞的线程。如果有多个线程,随机唤醒一个线程

下面是循环队列的使用

判断循环数组是否为空或满

1.牺牲一个空间

front == rear,即空状态 (rear + 1) % length == front即为满

2.设置一个标志,记录已经放的记录

int count; count == array.length即为满

这里我采用的是第二种方法

线程并发控制可以使用java sychronized进行同步

下面是具体实现

 1 public class Test {
 2     public static void main(String[] args) {
 3         Box box = new Box();
 4         Thread producer = new Thread(new ProduceApple(box));
 5         Thread  customer = new Thread(new CustomApple(box));
 6
 7         producer.start();
 8         customer.start();
 9     }
10 }
11
12 class Box{
13     int boxLength = 5;                                                                        //box容量
14     int buff[] = new int[boxLength];
15     int putPoint = 0;
16     int getPoint = 0;
17     int boxCount = 0;                                                                        //box已经放的数量
18 }
19
20 //生产苹果,生产者
21 class ProduceApple implements Runnable{
22     Box box;
23
24     public ProduceApple(Box box) {
25         this.box = box;
26     }
27     @Override
28     public void run() {
29         while(true){
30             synchronized (box) {
31                 box.putPoint = box.putPoint % box.boxLength;
32                 if(box.boxCount == 5){                                                        //没有放苹果的地方,等待消费者消费苹果
33                     try {
34                         box.wait();
35                     } catch (InterruptedException e) {
36                         e.printStackTrace();
37                     }
38                 }//if
39                 else{                                                                        //生产一个苹果放到箱子中
40                     box.buff[(++box.putPoint) % box.boxLength] = 1;
41                     box.boxCount++;
42                     System.out.println("放进一个苹果");
43                     System.out.println("苹果总数:" + box.boxCount);
44                     box.notify();
45                     try {
46                         Thread.sleep(1000);
47                     } catch (InterruptedException e) {
48                         e.printStackTrace();
49                     }
50                 }//else
51
52             }
53         }
54
55     }
56 }
57
58 //消费苹果,消费者
59 class CustomApple implements Runnable{
60     Box box;
61     public CustomApple(Box box){
62         this.box = box;
63     }
64     @Override
65     public void run() {
66         while(true){
67             synchronized (box) {
68                 box.getPoint = box.getPoint % box.boxLength;
69                 if(box.boxCount == 0){                                                            //没有可以吃的苹果,等待生产者生产苹果
70                     try {
71                         box.wait();
72                     } catch (InterruptedException e) {
73                         e.printStackTrace();
74                     }
75                 }//if
76                 else{                                                                            //吃掉一个苹果,唤醒生产者
77                     box.buff[(++box.getPoint) % box.boxLength] = 0;
78                     System.out.println("吃掉一个苹果");
79                     box.boxCount--;
80                     System.out.println("苹果总数:" + box.boxCount);
81                     box.notify();
82
83                     try {
84                         Thread.sleep(1000);
85                     } catch (InterruptedException e) {
86                         // TODO Auto-generated catch block
87                         e.printStackTrace();
88                     }
89                 }//else
90             }
91         }
92
93     }
94
95 }
时间: 2024-12-09 18:03:11

java 模拟实现消费者和生产者问题的相关文章

Java程序设计之消费者和生产者

新建一个Break类,表示食物数量. public class Break { public static final int MAX = 10; //最多一次性煮十个面包 Stack<Integer> stack = new Stack<Integer>(); public static int food_count = 0; //统计食物的个数 //做面包 public synchronized void make_food(int number){ stack.push(nu

[Java基础] java多线程关于消费者和生产者

多线程: 生产与消费1.生产者Producer生产produce产品,并将产品放到库存inventory里:同时消费者Consumer从库存inventory里消费consume产品.2.库存inventory的总量(最大库存量100)是有限的.如果库存inventory满了,生产者不能在库存inventory继续生产produce产品,须等待状态.等待产品被消费者Consumer消费consume了,再往库存inventory生产produce产品.3.若库存inventory空了,消费者Co

Java模拟生产者消费者问题

一.Syncronized方法详解 解决生产者消费这问题前,先来了解一下Java中的syncronized关键字. synchronized关键字用于保护共享数据.请大家注意"共享数据",你一定要分清哪些数据是共享数据,如下面程序中synchronized关键字保护的不是共享数据(其实在这个程序中synchronized关键字没有起到任何作用,此程序的运行结果是不可预先确定的).这个程序中的t1,t2是 两个对象(pp1,pp2)的线程.JAVA是面向对象的程序设计语言,不同的对象的数

java模拟实现生产者---消费者问题

本文章为小编原创,请尊重文章的原创性,转载请注意写明转载来源:http://blog.csdn.net/u012116457 已知技术参数: 生产者消费者问题,描述一组生产者向一组消费者提供产品/消息.它们共享一个有界缓冲区,生产者向其中放产品/消息,消费者从中取产品/消息.只要缓冲区未满,生产者可放产品/消息,只要缓冲区有数据,消费者可取消息.即应满足下列二个同步条件: 1.只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才能从中提取消息,否则消费者必须等待. 2.只有缓冲池中至少有一个缓冲

java 多线程并发系列之 生产者消费者模式的两种实现

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式. 什么是生

java线程之多个生产者消费者2.0

上一节中,通过while和notifyAll解决了多个生产者,消费者对共享资源的访问问题,现在开始升级 但是,仍然有改进之处,主要体现在两点: 1)使用新版本1.5开始后的锁Lock解决,目的将其全部替换实现相同功能 2)由于notifyAll唤醒的是己方和对方线程,我们优化的是只唤醒对方进程 方案1,使用while和notifyAll,synchronized解决多线程访问 代码: /* ProducterConsumerDemo解决了只有两个线程共享资源的生产消费问题,主要利用标志位的互斥解

java多线程 生产消费者模型

[seriesposts sid=500] 下面的代码讲述了一个故事 一个面包生产铺里目前有30个面包,有三个人来买面包,第一个人要买50个,第二个要买20个,第三个要买30个. 第一个人不够,所以等着,让第二个买了.面包铺继续生产面包.有7个人在生产. package com.javaer.thread; public class CPMode { public static void main(String[] args) { Godown godown = new Godown(30);

java模拟而一个电话本操作

哈哈,大家平时都在使用电话本,下面使用java来模拟而一个简单的电话本吧... 首先给出联系人的抽象类 package net.itaem.po; /** * * 电话人的信息 * */ public class User { private String name; private String phoneNumber; private String companyName; private String email; private String address; private Strin

java模拟手动Telnet过程之需求说明和功能点说明

一.需求 (一)每五分钟查询一次交换机的连接情况: (二)每2.5分钟更新每栋楼的连接情况. 二.功能点 序号 功能点说明 待定 完成 未完成 完成时间 预计用时(min) 实际用时(min) 备注 1 登录口令加密以及解密         60     2 表的创建和IP以及口令写入数据库         10     3 java模拟手动Telnet交换机         90     4 获取目标字符串         30     5 表的创建与当前目标数据的写入         10