java之生产者与消费者


package com.produce;

import java.util.LinkedList;
import java.util.Queue;

/*@author shijin
* 生产者与消费者模型中,要保证以下几点:
* 1 同一时间内只能有一个生产者生产 生产方法加锁sychronized
* 2 同一时间内只能有一个消费者消费 消费方法加锁sychronized
* 3 生产者生产的同时消费者不能消费 生产方法加锁sychronized
* 4 消费者消费的同时生产者不能生产 消费方法加锁sychronized
* 5 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行
* 6 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行
*/

//主类
public class ProducerConsumer
{
public static void main(String[] args)
{
StackBasket s = new StackBasket();
Producer p = new Producer(s);
Consumer c = new Consumer(s);
Thread tp = new Thread(p);
Thread tc = new Thread(c);
tp.start();
tc.start();
}
}

/**
* 馒头
* */
class Mantou
{
private int id;

Mantou(int id){
this.id = id;
}

public String toString(){
return "馒头ID" + id;
}
}

/**
* 共享栈空间 仓库
* */
class StackBasket
{
Queue<Mantou> sm = new LinkedList<Mantou>();
int index = 6;

/**
* show 生产方法.
* show 该方法为同步方法,持有方法锁;
* show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费;
* show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态,
* show 等生产结束释放同步方法锁后消费才能持有该锁进行消费
* @param m 元素
* @return 没有返回值
*/

public synchronized void push(Mantou m){
try{
while(index == sm.size()){
System.out.println("!!!!!!!!!生产满了!!!!!!!!!");
this.wait();
}
this.notify();
}catch(InterruptedException e){
e.printStackTrace();
}catch(IllegalMonitorStateException e){
e.printStackTrace();
}

sm.offer(m);
System.out.println("生产了:" + m + " 仓库有:" + sm.size() + "个馒头");
}

/**
* show 消费方法
* show 该方法为同步方法,持有方法锁
* show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产;
* show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态
* show 等消费结束释放同步方法锁后生产才能持有该锁进行生产
* @param b true 表示显示,false 表示隐藏
* @return 没有返回值
*/
public synchronized Mantou pop(){
try{
while(sm.size() == 0){
System.out.println("!!!!!!!!!消费光了!!!!!!!!!");
this.wait();
}
this.notify();
}catch(InterruptedException e){
e.printStackTrace();
}catch(IllegalMonitorStateException e){
e.printStackTrace();
}
Mantou mantou=sm.poll();
System.out.println("消费了:" + mantou + " 仓库有:" + sm.size() + "个馒头");
return mantou;
}
}

/**
* 生产者
* */
class Producer implements Runnable
{
StackBasket ss = new StackBasket();
Producer(StackBasket ss){
this.ss = ss;
}

/**
* show 生产进程.
*/
public void run(){
for(int i = 0;i < 20;i++){
Mantou m = new Mantou(i);
ss.push(m);
// System.out.println("生产了:" + m + " 共" + ss.index + "个馒头");
// 在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱
try{
Thread.sleep((int)(Math.random()*500));
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

/**
* 消费者
* */
class Consumer implements Runnable
{
StackBasket ss = new StackBasket();
Consumer(StackBasket ss){
this.ss = ss;
}

/**
* show 消费进程.
*/
public void run(){
for(int i = 0;i < 20;i++){
Mantou m = ss.pop();
//System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头");
//同上 在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱
try{
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

输出结果:


!!!!!!!!!消费光了!!!!!!!!!
生产了:馒头ID0 仓库有:1个馒头
消费了:馒头ID0 仓库有:0个馒头
生产了:馒头ID1 仓库有:1个馒头
生产了:馒头ID2 仓库有:2个馒头
生产了:馒头ID3 仓库有:3个馒头
消费了:馒头ID1 仓库有:2个馒头
生产了:馒头ID4 仓库有:3个馒头
消费了:馒头ID2 仓库有:2个馒头
生产了:馒头ID5 仓库有:3个馒头
消费了:馒头ID3 仓库有:2个馒头
生产了:馒头ID6 仓库有:3个馒头
生产了:馒头ID7 仓库有:4个馒头
生产了:馒头ID8 仓库有:5个馒头
消费了:馒头ID4 仓库有:4个馒头
生产了:馒头ID9 仓库有:5个馒头
生产了:馒头ID10 仓库有:6个馒头
!!!!!!!!!生产满了!!!!!!!!!
消费了:馒头ID5 仓库有:5个馒头
生产了:馒头ID11 仓库有:6个馒头
!!!!!!!!!生产满了!!!!!!!!!
消费了:馒头ID6 仓库有:5个馒头
生产了:馒头ID12 仓库有:6个馒头
!!!!!!!!!生产满了!!!!!!!!!
消费了:馒头ID7 仓库有:5个馒头
生产了:馒头ID13 仓库有:6个馒头
消费了:馒头ID8 仓库有:5个馒头
消费了:馒头ID9 仓库有:4个馒头
生产了:馒头ID14 仓库有:5个馒头
生产了:馒头ID15 仓库有:6个馒头
消费了:馒头ID10 仓库有:5个馒头
生产了:馒头ID16 仓库有:6个馒头
!!!!!!!!!生产满了!!!!!!!!!
消费了:馒头ID11 仓库有:5个馒头
生产了:馒头ID17 仓库有:6个馒头
!!!!!!!!!生产满了!!!!!!!!!
消费了:馒头ID12 仓库有:5个馒头
生产了:馒头ID18 仓库有:6个馒头
消费了:馒头ID13 仓库有:5个馒头
生产了:馒头ID19 仓库有:6个馒头
消费了:馒头ID14 仓库有:5个馒头
消费了:馒头ID15 仓库有:4个馒头
消费了:馒头ID16 仓库有:3个馒头
消费了:馒头ID17 仓库有:2个馒头
消费了:馒头ID18 仓库有:1个馒头
消费了:馒头ID19 仓库有:0个馒头

时间: 2024-10-08 10:59:39

java之生产者与消费者的相关文章

Java多线程--生产者与消费者问题

说明 Java中,线程之间的通信主要是由java.lang.Object类提供的wait.notify和notifyAll这3个方法来完成: ①对象的wait方法被调用后,线程进入对象的等待队列中,并释放对象锁,其它线程可以竞争使用此对象锁:sleep方法使得一个线程进入睡眠状态,但是线程所占有的资源并没有释放. ②当对象的notify方法被调用,该方法会从对象的等待队列中随机取出一个线程来唤醒:notifyAll是唤醒等待队列中所有线程,这些线程会与其它正在执行的线程共同竞争对象锁. ③wai

java线程 生产者与消费者

package org.rui.thread.block; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 生产者与消费者 * 餐馆 * * @author lenovo * */ public class Restaurant { //Restaurant r=new Restaurant

Java实现生产者和消费者

生产者和消费者问题是操作系统的经典问题,在实际工作中也常会用到,主要的难点在于协调生产者和消费者,因为生产者的个数和消费者的个数不确定,而生产者的生成速度与消费者的消费速度也不一样,同时还要实现生产者与消费者的解耦,即生产者并不知道有哪些消费者,而消费者也不需要知道产品是哪个生产的,他们之间只与一个交易平台发生关系. 这是现实世界普遍存在的问题,比如我们去苹果专卖店买IPhone 6,我们属于消费者,而生产商把产品生产出来放在苹果专卖店,如果全世界只有一个苹果专卖店,当专卖店没有IPhone 6

java之生产者和消费者问题

package testThread; public class Test3 { public static void main(String[] args) { Clerk c = new Clerk(); //消费时不生产,生产时不消费 //生产者 new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub synchronized (c) { //无限生产 whil

RabbitMQ简单Java示例——生产者和消费者

添加Maven依赖: 使用rabbitmq-client的最新Maven坐标: <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.3.0</ver

java多线程:生产者和消费者模式(wait-notify) : 单生产和单消费

单生产者 package com.example.t.pc; import java.util.List; //生产者 public class P { private List list; public P(){ } public P(List list){ this.list = list; } public void add(){ while(true){ synchronized (list){ try { System.out.println("3s----------------&q

使用JUC并发工具包的Lock和Condition,实现生产者和消费者问题中的有界缓存

JDK5.0之前,用java实现生产者和消费者的唯一方式就是使用synchronized内置锁和wait/notify条件通知机制.JDK5.0之后提供了显示锁Lock和条件队列Condition,与内置锁和内置条件队列相对应,但是显示的锁和条件队列,功能更强大,更灵活.此外JDK5.0之后还提供了大量很有用的并发工具类,如BlockingQueue等,基于这些数据结构,能够方便.快速.高效的构建自己应用需要的效果.这里我们简单使用下显示锁和条件队列,来模拟有界缓存的实现,功能类似于JDK内置的

Java模拟生产者消费者问题

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

Java中的生产者、消费者问题

Java中的生产者.消费者问题描述: 生产者-消费者(producer-consumer)问题, 也称作有界缓冲区(bounded-buffer)问题, 两个进程共享一个公共的固定大小的缓冲区(仓库). 其中一个是生产者, 用于将产品放入仓库: 另外一个是消费者, 用于从仓库中取出产品消费. 问题出现在当仓库已经满了, 而此时生产者还想向其中放入一个新的产品的情形, 其解决方法是让生产者此时进行等待, 等待消费者从仓库中取走了一个或者多个产品后再去唤醒它. 同样地, 当仓库已经空了, 而消费者还