生产者与消费者
        代码要求知道做什么用即可
        线程间的通讯问题以及 Object 类的支持
        
    基础模型
        现在希望实现一种数据的生产和取出的操作形式,即:有两个甚至更多的线程对象,这样的线程分为生产者线程和消费者线程
        那么最理想的状态是生产者每生产完一条完整的数据之后,消费者就要取走这个数据,并且进行输出的打印
        现在假设要输出的信息有这样两个:
            title = 帅帅, content = 一个学生;
            title = 可爱的小动物, content = 小猫咪;
            
        范例:程序的初期实现

package cn.mysterious.actualcombat;
class Info{
private String title;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producptor implements Runnable{
private Info info = null;
public Producptor(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
if (i % 2 == 0) { // 偶数
this.info.setTitle("帅帅");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("一个学生");
}else {
this.info.setTitle("可爱的动物");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("小猫咪");
}
}
} }
class Consumer implements Runnable{
private Info info = null;
public Consumer(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.info.getTitle() + "-->" + this.info.getContent());
}
}
}
public class ActualCombat{
public static void main(String[] args){
Info info = new Info();
Producptor p = new Producptor(info);
Consumer c = new Consumer(info);
new Thread(p).start();
new Thread(c).start(); }
}

通过以上的执行可以发现有两个问题:
            第一:数据错位了
            第二:重复生产,重复取出
            
    解决数据不同步问题
        要想解决同步问题一定使用同步代码块或者是同步方法,既然要同步,那么肯定要将设置属性和取得的属性的内容都统一交给 Info 完成
        
        范例:

package cn.mysterious.actualcombat;
class Info{
private String title;
private String content;
public synchronized void set(String content, String title){
this.title = title;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.content = content;
}
public synchronized void get(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.title + "-->" +this.content );
}
}
class Producptor implements Runnable{
private Info info = null;
public Producptor(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
if (i % 2 == 0) { // 偶数
this.info.set("帅帅","一个学生");
}else {
this.info.set("可爱的动物","小猫咪");
}
}
} }
class Consumer implements Runnable{
private Info info = null;
public Consumer(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
this.info.get();
}
}
}
public class ActualCombat{
public static void main(String[] args){
Info info = new Info();
Producptor p = new Producptor(info);
Consumer c = new Consumer(info);
new Thread(p).start();
new Thread(c).start(); }
}

所有的设置和取得数据的操作都交给了同步方法完成
            现在同步问题解决了,但是重复问题更严重了
            
    解决重复操作
        如果要想解决重复问题,那么必须加入等待与唤醒的处理机制,而这样的操作方法是有 Object 类所提供的
        在 Object 类中提供有如下几种方法:
            等待: public final void wait() throws InterruptedException{}
            唤醒第一个等待线程: public final void notify();
            唤醒全部等待线程: public final void notifyAll();
            
        范例:修改Info类

package cn.mysterious.actualcombat;
class Info{
private String title;
private String content;
private boolean flag = true;
// flag = true 表示可以生产,但是不允许取走数据
// flag = false 表示可以取走数据,但是不允许生产数据
public synchronized void set(String title, String content){
if (this.flag = false) { // 表示已经生产过了,还未取走
try {
super.wait(); // 等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // 没有生产,可以生产
this.title = title;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.content = content;
this.flag = false;// 表示生产过了
super.notify();
}
public synchronized void get(){
if (this.flag = true) { // 此时应该生产,不应该取走数据
try {
super.wait(); // 等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.title + "-->" +this.content );
this.flag = true; // 表示取走了
super.notify();
}
}
class Producptor implements Runnable{
private Info info = null;
public Producptor(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
if (i % 2 == 0) { // 偶数
this.info.set("帅帅","一个学生");
}else {
this.info.set("可爱的动物","小猫咪");
}
}
} }
class Consumer implements Runnable{
private Info info = null;
public Consumer(Info info){
this.info = info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
this.info.get();
}
}
}
public class ActualCombat{
public static void main(String[] args){
Info info = new Info();
Producptor p = new Producptor(info);
Consumer c = new Consumer(info);
new Thread(p).start();
new Thread(c).start(); }
}

面试题:请解释 sleep() 与 wait() 的区别?
            sleep() 是 Thread 类定义的方法,在休眠一定时间之后自己唤醒
            wait() 是 Object 类定义的方法,表示线程要等待执行,必须通过 notify(),notifyAll() 方法来进行唤醒

    总结
        生产者和消费者这是一个模型,完整的体现了线程的同步, Object 类的支持

菜鸡的Java笔记 生产者与消费者的更多相关文章

  1. 菜鸡的Java笔记 - java 断言

    断言:assert (了解)        所谓的断言指的是在程序编写的过程之中,确定代码执行到某行之后数据一定是某个期待的内容        范例:观察断言 public class Abnorma ...

  2. 菜鸡的Java笔记 - java 正则表达式

    正则表达式 RegularExpression        了解正则表达式的好处        正则表达式的基础语法        正则表达式的具体操作            content (内容 ...

  3. 菜鸡的Java笔记 数字操作类

    数字操作类        Math 类的使用        Random 类的使用        BigInteger 和 BigDecimal 类的使用                Math 是一 ...

  4. 菜鸡的Java笔记 - java 线程常用操作方法

    线程常用操作方法        线程的命名操作,线程的休眠,线程的优先级            线程的所有操作方法几乎都在 Thread 类中定义好了            线程的命名和取得      ...

  5. 菜鸡的Java笔记 日期操作类

    日期操作类        Date 类与 long 数据类型的转换        SimpleDateFormat 类的使用        Calendar 类的使用                如 ...

  6. 菜鸡的Java笔记 开发支持类库

    开发支持类库 SupportClassLibrary        观察者设计模式的支持类库                    content (内容)        什么是观察者设计模式呢?   ...

  7. 菜鸡的Java笔记 简单JAVA 类的开发原则以及具体实现

    /*  现在要求定义一个雇员信息类 在这个类之中包含有雇员编号 姓名 职位 基本工资 佣金等信息    对于此时给定要求实际上就是描述一类事物,而这样的程序类在在java之中可以将其称为简单java类 ...

  8. 菜鸡的Java笔记 - java 访问控制权限

    java中四种访问控制权限的使用                内容            在java里面一共定义有四个权限,按照由小到大的顺序:private<defaule<prote ...

  9. 菜鸡的Java笔记 国际化程序实现原理

    国际化程序实现原理 Lnternationalization        1. Locale 类的使用        2.国家化程序的实现,资源读取                所谓的国际化的程序 ...

随机推荐

  1. SSA

    wikipedia上关于SSA的定义如下: In compiler design, static single assignment form (often abbreviated as SSA fo ...

  2. 【MySQL】MySQL进阶(外键约束、多表查询、视图、备份与恢复)

    约束 外键约束 外键约束概念 让表和表之间产生关系,从而保证数据的准确性! 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数 ...

  3. 阿里云函数计算发布新功能,支持容器镜像,加速应用 Serverless 进程

    我们先通过一段视频来看看函数计算和容器相结合后,在视频转码场景下的优秀表现.点击观看视频 >> FaaS 的门槛 Serverless 形态的云服务帮助开发者承担了大量复杂的扩缩容.运维. ...

  4. 回归本心QwQ背包问题luogu1776

    今天在这里说一下多重背包问题 对 之前一直没有怎么彻底理解 首先多重背包是什么?这里就不做过多的赘述了 朴素的多重背包的复杂度是\(O(n*m*\sum s[i])\),其中\(s[i]\)是每一件物 ...

  5. PAT (Basic Level) Practice (中文)1017 A除以B (20分)

    1017 A除以B (20分) 本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立. 输入格式: 输入在一 ...

  6. 用C++生成solidity语言描述的buchi自动机的初级经验

    我的项目rvtool(https://github.com/Zeraka/rvtool)中增加了生成solidity语言格式的监控器的模块. solidity特殊之处在于,它是运行在以太坊虚拟机环境中 ...

  7. Vulnhub实战-grotesque3靶机👻

    Vulnhub实战-grotesque3靶机 靶机地址:http://www.vulnhub.com/entry/grotesque-301,723/ 1.靶机描述 2.主机探测,端口扫描 我们在vm ...

  8. Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!

    Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...

  9. 吴恩达课后习题第二课第三周:TensorFlow Introduction

    目录 第二课第三周:TensorFlow Introduction Introduction to TensorFlow 1 - Packages 1.1 - Checking TensorFlow ...

  10. 8.18考试总结[NOIP模拟43]

    又挂了$80$ 好气哦,但要保持优雅.(草 T1 地衣体 小小的贪心:每次肯定从深度较小的点向深度较大的点转移更优. 模拟一下,把边按链接点的子树最大深度排序,发现实际上只有上一个遍历到的点是对当前考 ...