博客园的园友们好,看博客园上各位大佬的文章,已陪伴了我程序员职业的三年,

如今自己同样希望能把自己从小白到菜鸟的成长过程分享给大家。不定期更新!!!

首先我本人智商不高,理解问题十分吃力,完全不属于天才的行列,因此学习每一个知识

都喜欢刨根问底,结合生活,彻彻底底理解知识的本质!

进入正题,这篇文章,主要站在一个初学者的角度,结合经典的“生产者消费者模型”,写一个java多线程例子!

首先解释几个概念:

  1、#进程:通俗的讲,就是一个程序一次执行的过程。是系统进行资源分配和调度的一个独立单位。

  2、#线程:一个进程的生命周期,由一个或若干个线程完成。是CPU调度和分派的基本单位。

  3、#并行:同一时间点或者时间段,可以处理超过一个任务的能力。

  eg:你正在lol,女朋友来电话,于是你单手操作或者侧头夹住手机,既聊天又打团,这就是你自己并行处理了,

撩妹和打游戏。这个过程,你就类似于cpu,前提你是多核。

  4、#并发:主要针对多线程提出的概念。可以在一个时间段,交替执行不同事情的能力。

  eg:你正在lol,女朋友来电话,于是你挂机去接电话,然后打完电话回来面对腾讯的裁决。或者你等着打完团,然后

面对女友的生气。这就是并发,你交替执行了不同事情。这个过程,你也类似于cpu,可以不用多核。

二、简单代码实现多线程

  2.1模型图

注释:张全蛋经过自己的努力,进入富士康工厂工作,主要负责生产时下流行的iPhoneXs,然后广大果粉在库存充足的情况下购买iPhoneXs。

这个过程共涉及以下角色和过程:

  1、生产者(张全蛋)。

  2、消费者(广大果粉)。

  3、产品(iPhoneXs)。

  4、生产产品,购买产品。

2.2 程序展示

  2.2.1  产品类

由于我们此次实验过程,主要涉及生产产品,所以我们可以忽略产品本身具有的属性和方法。

 package com.dcits.weipt;

 /**
* 产品实体类
* 因我们此次实验是针对生产产品
* 所以我们忽略产品本身所具有的方法和属性
* @author weipt
* @date 20180915*/
public class Product { }

  2.2.2 工厂类

工厂类用于生产产品,需要注意的是,在java中,生产一个产品,就是new一个产品类的实体对象。

 package com.dcits.weipt;

 import java.util.ArrayList;
import java.util.List; /**
* 生产产品的工厂类
* 生产一个产品则意味着new一个产品对象
* 消费一个产品则意味着remove一个对象
* @author weipt
* @date 20180915*/ public class ProductFactory {
private List<Product> list = new ArrayList<Product>(); //利用list保存对象 /**
* 工厂生产产品的方法
* 单位时间生产3个
* */
public void makeProduct() {
for(int i=0;i<3;i++) {
list.add(new Product());
}
} /**
* 工厂消费产品的方法
* 单位时间消费1个*/
public void moveProduct() {
list.remove(0);
} /**
* 获取产品个数*/
public int getNum() {
return list.size();
} }

  2.2.3 生产者

用于不断调用工厂类,生产产品。每当我们生产一次产品,需要调用notify/notifyAll通知或唤醒消费者来购买。

但当我们生产超过max,需要调用wait,等待消费者购买,减少库存。

 package com.dcits.weipt;

 /**
*生产者实体类
* @author weipt
* @date 20180915*/ public class Producer implements Runnable {
private final int MAX_PRODUCT = 30;
private ProductFactory pf; public Producer(ProductFactory pfIn) {
this.pf = pfIn;
} @Override
public void run() {
produce();
} /**
* 生产者生产,产品
*/
public void produce() {
while (true) {
synchronized (pf) {
if (pf.getNum() >= MAX_PRODUCT) {
try {
System.out.println("warnning! 库存已满,请稍微再生产!");
pf.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
pf.makeProduct();
System.out.println("P---》生产者生产了第【" + pf.getNum() + "】个产品");
pf.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

  2.2.4 消费者

用于不断调用工厂类,购买产品。每当我们购买一次产品,需要调用notify/notifyAll通知或唤醒生产者去生产。

但当库存小于min,需要调用wait,等待生产者,增加库存。

 package com.dcits.weipt;

 /**
* 消费者实体类
* @author weipt
* @date 20180915*/ public class Consumer implements Runnable {
private final int MIN_PRODUCT = 0; //产品最小值
private ProductFactory pf; //产品工厂对象 /**
* 通过构造方法获取产品对象*/
public Consumer(ProductFactory pfIn) {
this.pf = pfIn;
} @Override
public void run() {
consume();
} /**
* 消费者从库存中取产品
*/
public void consume() {
while (true) {
synchronized (pf) { //因为生产者和消费者都是对产品操作,所以对产品进行加锁
if (pf.getNum() <= MIN_PRODUCT) {
try {
System.out.println("warnning! 库存已空,请稍微再取!");//注意顺序,要放到wait之前
pf.wait(); //等待其他线程操作,直到收到其他线程的notify
//此处我没有写notify,因为库存缺货,就只能等生产者生产,唤醒其他消费者没有用
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println("C---》消费者取走了第【" + pf.getNum() + "】个产品");
pf.moveProduct(); //产品出库
pf.notifyAll(); //通知生产者可以继续生产
}
try {
Thread.sleep(1000); //防止日志打印过多,没有可观性
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} }

  2.2.5 开始工作

在main方法中,开启消费者和生产者线程。

 package com.dcits.weipt;

 /**
* 公司领导
* 用于让整个系统运作起来*/ public class HelloThread{
public static void main(String[] args) {
ProductFactory pf = new ProductFactory();
Producer p = new Producer(pf);
Consumer c = new Consumer(pf);
Thread pt = new Thread(p);
Thread ct = new Thread(c);
pt.start(); //我们可以开启多个消费者或者多个生产者
ct.start();
}
}

到这里,这篇文章就彻底结束了。

注:如需索要编译好的项目源码可关注公众号mht18391859179(扫描下方二维码),回复:  免费领取

如果需要交流或者指正,可通过上述公众号,或者email:wpt191@163.com与本人联系。

笨鸟先飞,终生学习

特别鸣谢:

  1、感谢胡**,同志的交流与指导。

  2、感谢博客园,csdn,知乎等大牛文章的启迪。

结合生活,剖析《生产者消费者模型》-java多线程(一)的更多相关文章

  1. 生产者消费者模型Java实现

    生产者消费者模型 生产者消费者模型可以描述为: ①生产者持续生产,直到仓库放满产品,则停止生产进入等待状态:仓库不满后继续生产: ②消费者持续消费,直到仓库空,则停止消费进入等待状态:仓库不空后,继续 ...

  2. 生产者消费者模型java

    马士兵老师的生产者消费者模型,我感觉理解了生产者消费者模型,基本懂了一半多线程. public class ProducerConsumer { public static void main(Str ...

  3. 生产者消费者模型-Java代码实现

    什么是生产者-消费者模式 比如有两个进程A和B,它们共享一个固定大小的缓冲区,A进程产生数据放入缓冲区,B进程从缓冲区中取出数据进行计算,那么这里其实就是一个生产者和消费者的模式,A相当于生产者,B相 ...

  4. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

  5. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  6. Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型

    http://blog.csdn.net/a352193394/article/details/39503857  Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...

  7. Java多线程-并发协作(生产者消费者模型)

    对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓 ...

  8. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  9. java 线程池、多线程实战(生产者消费者模型,1 vs 10) 附案例源码

    导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...

随机推荐

  1. AI:是猫还是狗,这是个问题

    如果你不喜欢小猫和小狗,你可能不知道他们具体是哪一种品种,但是一般来说,你都能区分出这是猫还是狗,猫和狗的特征还是不一样的,那我们如何用机器学习的方法训练一个网络区分猫狗呢? 我们选用的是 Kaggl ...

  2. C++走向远洋——51(数组类运算的实现)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  3. 创建SpringMVC项目过程

    1.导入对应jar包 <properties> <spring.version>5.0.2.RELEASE</spring.version> </proper ...

  4. LeetCode 题解 | 1. 两数之和

    题目描述: 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], t ...

  5. python数组和字符串互相转换

    字符串转数组 str = '1,2,3' arr = str.split(',') 数组转字符串 arr = ['a','b'] str = ','.join(arr) arr = [1,2,3] s ...

  6. 如何在普通的元素上实现enter键的绑定

    在做登录页面时候,通常当用户输入账号密码后直接按enter键就触发登录按钮了. 如果是input标签,vue中可以绑定按键修饰符,但是如果是其它标签呢.我的做法如下: document.querySe ...

  7. PHP数组的升序降序函数

    数组排序函数:::sort()对数组进行升序排列rsort()对数组进行降序排列 asort()根据关联数组的值,对数组进行升序排列ksort()根据关联数组的键,对数组进行升序排列 arsort() ...

  8. django 从零开始 6 数据库模型增删改查

    这些都是凭记忆写下的,有些会漏掉,在之后的笔记中会写 和flask query不同,django是使用objects进行一个查询 查询 单条记录 django 模型.bojects.get(查询的字段 ...

  9. Redis03——Redis是如何删除你的数据的

    众所周知Redis针对每一个key都能单独设置过期时间,那么Redis是怎么处理这些key的过期时间的呢?当同一时间有大量Key同时到期时,Redis又是怎么处理的呢?会不会影响到我的线上业务呢?如果 ...

  10. 第3章 C++中的C

    用union节省内存 使用场合:有时一个程序会使用同一个变量处理不同的数据类型,对于这种情况,有两种选择:可以创建一个struct,其中包含所有可能的不同类型的数据:也可以使用联合union,它能把所 ...