题目要求

用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. Serialization之SOAP序列化

    前言 XML序列化还可用于对象序列化符合SOAP规范的XML流.SOAP是一种简单的基于XML的协议,它使应用程序通过HTTP来交换信息.专门为使用XML来传输过程调用而设计的.如同常规的XML序列化 ...

  2. 魔法少女 LJJ——线段树

    题目 [题目描述] 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女 LJJ 已经觉得自己见过世界上的所有稀奇古怪的事情了. LJJ 感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处 ...

  3. Error: connection reset by peer ,during filebeat connect to elk.

    Error screenshot like below: Reason: What I found that was the machine failing had same configuratio ...

  4. MobaXterm替换cmder

    Windows上命令行工具cmder确实很好用,其扩展功能呢,比系统自带强大几倍.后来在使用MobaXterm,官网https://mobaxterm.mobatek.net/免费版本功能足够强大,支 ...

  5. Leetcode 70. Climbing Stairs 爬楼梯 (递归,记忆化,动态规划)

    题目描述 要爬N阶楼梯,每次你可以走一阶或者两阶,问到N阶有多少种走法 测试样例 Input: 2 Output: 2 Explanation: 到第二阶有2种走法 1. 1 步 + 1 步 2. 2 ...

  6. 数据结构31:树(Tree)详解

    复制广义表数据结构中的树 树是数据结构中比较重要也是比较难理解的一类存储结构.本章主要主要围绕二叉树,对树的存储以及遍历做详细的介绍,同时还会涉及到有关树的实际应用,例如构建哈弗曼编码等. 由于树存储 ...

  7. zookeeper客户端使用第三方(Curator)封装的Api操作节点

    1.为什么使用Curator? Curator本身是Netflix公司开源的zookeeper客户端: Curator  提供了各种应用场景的实现封装: curator-framework  提供了f ...

  8. How to pass multiple parameters in PowerShell invoke-restmethod

    Link: http://www.tagwith.com/question_322855_how-to-pass-parameters-in-powershell-invoke-restmethod- ...

  9. Apache 在 htaccess 禁止访问 和 conf 中的 禁止访问 区别

    相信熟悉Web Server的人一定熟悉Apahce.相信熟悉Apahce的人一定知道URL Rewrite.Apache的mod_rewrite模块,可以帮助人们构造出各种各样美化后的URL.在Ap ...

  10. Linq 查询内建议不要使用运算语句!

    比如list有2个值,当你运行完上述代码后,你会发现,你的ls中的Num没有按你预期的那样从0开始,导致这个问题的原因是:在你查询完毕后,执行的Count()方法,会导致查询语句中Num=num++再 ...