题目要求

用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进行同步

下面是具体实现

 public class Test {
public static void main(String[] args) {
Box box = new Box();
Thread producer = new Thread(new ProduceApple(box));
Thread customer = new Thread(new CustomApple(box)); producer.start();
customer.start();
}
} class Box{
int boxLength = 5; //box容量
int buff[] = new int[boxLength];
int putPoint = 0;
int getPoint = 0;
int boxCount = 0; //box已经放的数量
} //生产苹果,生产者
class ProduceApple implements Runnable{
Box box; public ProduceApple(Box box) {
this.box = box;
}
@Override
public void run() {
while(true){
synchronized (box) {
box.putPoint = box.putPoint % box.boxLength;
if(box.boxCount == 5){ //没有放苹果的地方,等待消费者消费苹果
try {
box.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//if
else{ //生产一个苹果放到箱子中
box.buff[(++box.putPoint) % box.boxLength] = 1;
box.boxCount++;
System.out.println("放进一个苹果");
System.out.println("苹果总数:" + box.boxCount);
box.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//else }
} }
} //消费苹果,消费者
class CustomApple implements Runnable{
Box box;
public CustomApple(Box box){
this.box = box;
}
@Override
public void run() {
while(true){
synchronized (box) {
box.getPoint = box.getPoint % box.boxLength;
if(box.boxCount == 0){ //没有可以吃的苹果,等待生产者生产苹果
try {
box.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//if
else{ //吃掉一个苹果,唤醒生产者
box.buff[(++box.getPoint) % box.boxLength] = 0;
System.out.println("吃掉一个苹果");
box.boxCount--;
System.out.println("苹果总数:" + box.boxCount);
box.notify(); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//else
}
} } }

-------------------------------------------------我是分割线-----------------------------------------------

可以使用BlockingQueue来进行模拟

ProducerAndConsumer.java

 import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import com.gxf.util.Util; /**
* 利用BlockingQueue实现生产者和消费者问题
* @author Administrator
*
*/
public class ProducerAndConsumer { //产品队列
private static int queueLength = 5;
private static BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(queueLength); /**
* 模拟生产者
* @author Administrator
*
*/
static class ProducerScript implements Runnable{
//生产者名字
private String name; public ProducerScript(String name) {
this.name = name;
} @Override
public void run() {
//生产者开始生产
while(true){
int product = Util.generateRandomInt();
try {
blockingQueue.put(product);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println(name + ":" + product);
System.out.println(blockingQueue);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} } } /**
* 模拟消费者
* @author Administrator
*
*/
static class ConsumerScript implements Runnable{
private String name; public ConsumerScript(String name) {
this.name = name;
} @Override
public void run() {
//消费者开始消费
while(true){
int product = -1;
try {
product = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + ":" + product);
System.out.println(blockingQueue);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} } } /**
* 测试程序
* @param args
*/
public static void main(String args[]){
ProducerScript producer = new ProducerScript("生产"); ConsumerScript consumer = new ConsumerScript("消费"); Thread producerThread = new Thread(producer);
// Thread producerThread1 = new Thread(producer);
Thread consumerThread = new Thread(consumer);
// Thread consumerThread1 = new Thread(consumer); producerThread.start();
consumerThread.start();
// consumerThread1.start();
// producerThread1.start();
}
}

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

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

    新建一个Break类,表示食物数量. public class Break { public static final int MAX = 10; //最多一次性煮十个面包 Stack<Inte ...

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

    多线程: 生产与消费 1.生产者Producer生产produce产品,并将产品放到库存inventory里:同时消费者Consumer从库存inventory里消费consume产品. 2.库存in ...

  3. 消费者与生产者---LinkedList方式模拟

    采用LinkedList数据结构方式来模拟消费者与生产者模型,小Demo import java.util.LinkedList; public class MyQueue { private fin ...

  4. Java笔记1 : 在生产者消费者模式中,线程通信与共享数据,死锁问题与解决办法

    本例定义了4个类,这里说一下,方便下面讲解.分别是Product(产品),Producer(生产者),Consumer(消费者), Test(测试类). 多线程之间通信与共享数据只要引用同一内存区域就 ...

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

    上一节中,通过while和notifyAll解决了多个生产者,消费者对共享资源的访问问题,现在开始升级 但是,仍然有改进之处,主要体现在两点: 1)使用新版本1.5开始后的锁Lock解决,目的将其全部 ...

  6. Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例

    Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...

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

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  8. java并发:初探消费者和生产者模式

    消费者和生产者模式 用继承Thread方式,用wait和notifyAll方法实现. 消费者和生产者模式的特点 1. 什么时候生产:仓库没有满的时候,生产者这可以生产,消费者也可以消费,仓库满的时候停 ...

  9. java多线程-消费者和生产者模式

    /* * 多线程-消费者和生产者模式 * 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象 * */ /*资源类中定义了name( ...

随机推荐

  1. java volatile 关键字(转)

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...

  2. 计算机上配置 IP地址,子网掩码,默认网关

    The Internet Assigned Numbers Authority (IANA) has reserved the following three blocks of the IP add ...

  3. ThinkPHP CURD 操作

    Thinkphp CURD操作php中实例还对象即可操作 (目录) 1.Add 1 调式程序 3 调出显示页面Trace信息 3 Dump 的含义 4 2.数据库查询 4 1.直接使用字符串进行查找 ...

  4. React-Native App启动页制作(安卓端)

    原文地址:React-Native App启动页制作(安卓端) 这篇文章是根据开源项目react-native-splash-screen来写的.在使用react-native-link命令安装该包后 ...

  5. 去除掉svn目录

    使用svn提交时,造成有些文件锁住不能使用,百度得到下面相似问题以及解决方法: /*********************************************************** ...

  6. Qt 学习之路 2(16):深入 Qt5 信号槽新语法

    Qt 学习之路 2(16):深入 Qt5 信号槽新语法  豆子  2012年9月19日  Qt 学习之路 2  53条评论 在前面的章节(信号槽和自定义信号槽)中,我们详细介绍了有关 Qt 5 的信号 ...

  7. EA添加流程图

  8. vue项目中打包编译后,CSS样式【-webkit-box-orient: vertical】打包后丢失问题

    最近在做vue项目的时候页面处理多行文本样式时用到了-webkit-box-orient: vertical这个属性,本地跑项目没问题,但是打包放到服务器后发现这个属性丢失了.如下图: 后来在网上查了 ...

  9. 编译 OpenWrt/LEDE 基本过程

    说明 前段时间花 110 从闲鱼淘了个 Newifi D1,这个路由的 Soc 是 MT7621AT,性能强劲,于是又开始折腾编译固件了,重新记录一下编译基本过程. 步骤 安装必要的软件包 sudo ...

  10. Oulipo (KMP出现次数)

    The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e ...