生产者与消费者
        代码要求知道做什么用即可
        线程间的通讯问题以及 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. join方法个人理解

    首先抛出对join的疑问 如果我有一个a线程,一个b线程 那此时 a.start(); b.start(); a.join(); b.join(); 是否意思是a线程先执行完,然后再执行b线程; 如果 ...

  2. firewalld防火墙详解

    众所周知,在RHEL7系统中,firewalld防火墙取代了iptables防火墙.我们都知道iptables的防火墙策略是交由内核层面的netfilter网络过滤器来处理的,而firewalld则是 ...

  3. Spring源码之AOP的使用

    Spring往期精彩文章 Spring源码搭建 Spring源码阅读一 前言 我们都知道Java是一门面向对象(OOP)的语言,所谓万物皆对象.但是它也存在着一些个弊端:当你需要给多个不具有继承关系的 ...

  4. Python - poetry(1)包管理利器的入门介绍

    Python 虚拟环境详解 https://www.cnblogs.com/poloyy/p/15266382.html poetry 官方介绍 github:https://github.com/p ...

  5. Java-爬虫-小项目

    爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了!) 项目地址:https://gitee.com/zwtgit/java-reptile 导入依赖,写一个工具类 <depend ...

  6. PLSQL安装,PLSQL汉化,激活

    一)准备工作 1.点击下载PLSQL:https://www.allroundautomations.com/registered-plsqldev/.本次安装的是12.0.7,安装版本为64位 2. ...

  7. pymysql基础

    一,基本使用 倒入模块 import pymysql conn=pymysql.connect( host="数据库地址,本机是localhost,别的机器是ip", user=& ...

  8. 题解 「BZOJ2137」submultiple

    题目传送门 题目大意 给出 \(M,k\) ,求出 \[\sum_{x|M}\sigma(x)^k \] 给出 \(P_i\),满足 \(n=\prod_{i=1}^{n}a_i^{P_i}\),其中 ...

  9. 内网渗透DC-2靶场通关(CTF)

    为了更好的阅读体验,请在pc端打开我的个人博客 DC系列共9个靶场,本次来试玩一下DC-2,共有5个flag,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware ...

  10. BUAA软件工程个人项目作业

    BUAA软件工程个人项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 学习软件开发的流程 这个作业在哪 ...