在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法。wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程。notify()方法是持有相同的对象锁来唤醒休眠的线程,使其具有抢占cpu的资格。可以理解同步方法,同步方法的对象锁就是谁调用这个方法,这个对象就是对象锁。

根据李兴华老师的视频讲解,建立一个生产者类,一个消费者类,还有一个Info类,贴上代码:

1.生产者类

package com.company;

/**
* Created by Administrator on 2016/8/30.
*/
public class Productor implements Runnable { private Info info; public Productor(Info info) {
this.info = info;
} @Override
public void run() { for (int i=0;i<50;i++)
{
if (i%2==0)
{
// info.setTitle("陶帅");
// info.setContent("一个帅哥");
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
info.set("陶帅","一个帅哥");
}else {
// info.setTitle("可爱的动物");
// info.setContent("草泥马");
info.set("可爱的动物","草泥马");
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
}
}

2.消费者类

package com.company;

/**
* Created by Administrator on 2016/8/30.
*/
public class Consumer implements Runnable {
private Info info; public Consumer(Info info) {
this.info = info;
} @Override
public void run() { for (int i=0;i<50;i++)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
info.get();
}
}
}

3.Info类(重点)

package com.company;

/**
* Created by Administrator on 2016/8/30.
*/
public class Info {
private String Title;
private String content;
private boolean flag=true;//true表示可以生产不能取走消费,false相反 public synchronized void set(String Titile,String content){
if (!flag)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.Title=Titile;
this.content=content;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} flag=false;
notify();
} public synchronized void get(){
if (flag)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.Title+"------->"+this.content);
flag=true;
notify();
} // public String getTitle() {
// return Title;
// }
//
// public void setTitle(String title) {
// Title = title;
// }
//
// public String getContent() {
// return content;
// }
//
// public void setContent(String content) {
// this.content = content;
// }
}

4.测试类

package com.company;

public class Main {

    public static void main(String[] args) {
Info info=new Info();
Productor p=new Productor(info);
Consumer c=new Consumer(info);
new Thread(p).start();
new Thread(c).start();
}
}

总结分析:生产者和消费者两个线程同时抢占CPU,假如消费者先抢到,此时调用get()方法即消费取走,但是此时flag为true,因此会进入wait()方法,所以此时只能是生产者抢占到CPU,根据生产者调用set()方法,生产后执行

        flag=false;
notify();

此时生产者和消费者所在的两个线程又站在同一起跑线上了,继续CPU争夺战。如果不幸的消费者又没有抢过生产者,生产者继续执行set();此时flag已经是false了,根据代码

 if (!flag)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

所以生产者只能乖乖的wait();CPU回到消费者这里,循环往复,模式就出来了,完美!

												

关于java中生产者消费者模式的理解的更多相关文章

  1. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  2. 转:Task任务调度实现生产者消费者模式 (个人理解后文)

    纯属个人愚见.欢迎加入反驳(PiDou). 1.前文大致就是,利用Queue配置的一个TaskFactory任务调度器.实现生产者消费者模式的例子..首先我就试了 第一种 FIFO(先进先出)的配置. ...

  3. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  4. java实现生产者消费者模式

    生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...

  5. java 实现生产者-消费者模式

    生产和消费者模式有很多种,现在介绍几种常见的方式 wait/notify实现生产和消费者模式 1.使用wait/notify实现生产和消费者模式: public class Depot { // 实际 ...

  6. java——利用生产者消费者模式思想实现简易版handler机制

    参考教程:http://www.sohu.com/a/237792762_659256 首先说一下这里面涉及到的线程: 1.mainLooper: 这个线程可以理解为消费者线程,里面运行了一个死循环, ...

  7. Java中生产者与消费者模式

    生产者消费者模式 首先来了解什么是生产者消费者模式.该模式也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了两个共享固定大小缓冲区的线 ...

  8. Java 生产者消费者模式详细分析

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  9. 基于Java 生产者消费者模式(详细分析)

    Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...

随机推荐

  1. 关于vue里页面的缓存

    keep-alive是vue内置的一个组件,可以使被它包含的组件处于保留状态,或避免被重新渲染. 用法: 运行结果描述: input输入框内,路由切换输入框内部的内容不会发生改变. 在keep-ali ...

  2. Node.js npm uuid

    nodejs 提供了一个 node-uuid 模块用于生成 uuid 使用方法为 const uuidV1 = require('uuid/v1'); uuidV1(); 或者为 const uuid ...

  3. 2156: 中南大学2018年ACM暑期集训前期训练题集(入门题) D: 机器人的指令

    不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! 不要用gets!不要用gets!不要用gets! ...

  4. ModuleNotFoundError: No module named 'Crypto.Cipher'

    ModuleNotFoundError: No module named 'Crypto.Cipher'报错问题 原因及处理: 在使用python3是经常会用到import一个第三方库,但是有时候会提 ...

  5. My thoughts after NOIP 2018(2)

    又一次陷入迷茫了呢. - 大概是因为是因为自招政策要改变了吧? - 大概是因为前路在一点一点变得难走吧? - 大概是因为OI和学习实在太难平衡了吧? 未来的一切都已经不再在我控制的范围之内,不迷茫才怪 ...

  6. java基础基础总结----- 关键字、标识符、注释、常量和变量、运算符、语句、函数、数组(三)

    Java语言基础组成:关键字.标识符.注释.常量和变量.运算符.语句.函数.数组 一.标识符 标识符是在程序中自定义的一些名称,由大小写字母[a-zA-Z],数字[0-9],下划线[ _ ],特殊字符 ...

  7. frp中的json模块

    预备知识 Go中的接口的数据结构可以分为两部分: 其中一部分指向或者存储了原始数据的值 另一部分指向或者存储了原始数据的类型描述符(其中包含类型,以及对应于接口中的方法) 所以大体上我们可以粗略的认为 ...

  8. 使用sed替换指定文件指定行的指定文本

    下面是将85行的127.0.0.1替换为192.168.10.108 sed -i '85{s/127.0.0.1/192.168.10.108/}' /etc/zabbix/zabbix_agent ...

  9. Nginx 学习笔记(三)proxy_cache 缓存配置和ngx_cache_purge模块

    反向代理的缓存清理 一.proxy_cache配置 (1)如何配置和安装,都在这里了:https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Ng ...

  10. Docker 入门 第五部分:Stacks

    目录 Docker 入门 第五部分:Stacks 先决条件 介绍 添加一个新的服务并重新部署 保存数据 回顾 Docker 入门 第五部分:Stacks 先决条件 安装 Docker 1.13 或更高 ...