=========================使用synchronized,配合Object的wait()/notify()实现生产者消费者======================

思考问题:

1.为什么用wait()+notify()实现生产者消费者模式?

wait()方法可以暂停线程,并释放对象锁
notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了synchronized临界区后,才会把锁释放

2.为什么wait()、notify()、notifyAll()方法需要放在同步代码块中执行?

wait()方法暂停线程执行,并立即释放对象锁

notify()/notifyAll() 方法唤醒其他等待该对象锁的线程,并在执行完同步代码块中的后续步骤后,释放对象锁

notify()和notifyAll()的区别在于:
notify只会唤醒其中一个线程,
notifyAll则会唤醒全部线程。 至于notify会唤醒哪个线程,是由线程调度器决定的。
因为这三个方法都需要获取到对象锁才能有效执行。否则就会抛异常:java.lang.IllegalMonitorStateException

3.wait()是暂停的哪个线程?notify()唤醒的是哪个线程?

wait()是暂停当前线程。

notify()则是唤醒等待当前对象锁的线程

4.什么是生产者消费者模式

一个产数据,一个用数据,中间最多再加上个存取仓库
生产者消费者模式 就是java多线程通信一个很好的例子

5.生产着消费者模式特点是什么

1.解耦,生产者干生产者的事情,消费者干消费者的事情

2.支持高并发,可以同时多个生成,多个消费,互不影响

6.一对一的生产者消费者模式:

  1>早餐类:

package com.sxd.swapping.test.ProducerAndConsumerTest;

/**
* 早餐基础类
*
* wait()
* notify()
* notifyAll()
* 三个方法 需要放在同步代码块中执行 因为要获取对象锁
*/
public class Breakfast{
private String food; private String drink; private boolean flag = false;//flag = false 表示需要生产 flag = true 表示需要消费 public synchronized void makeBreakfast(String food,String drink){ System.out.println("生产者进入--->标志值为:"+flag);
if (flag){
try {
System.out.println("make---wait()暂停,释放对象锁");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} this.food = food;
try {
System.out.println("make---sleep()休眠,不释放对象锁");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} this.drink = drink;
System.out.println("make---生产者制造东西完成----");
this.flag = true;
System.out.println("make---notify()唤醒,标志值为"+flag);
notify();
} public synchronized void eatBreakfast(){ System.out.println("消费者进入--->标志值为:"+flag);
if(!flag){
try {
System.out.println("eat---wait()");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} try {
System.out.println("eat---sleep()");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("吃东西---"+this.food+";喝东西---"+this.drink);
this.flag = false;
System.out.println("eat---notify()唤醒,标志值为"+flag);
notify();
}
}

  2> 生产者类:

package com.sxd.swapping.test.ProducerAndConsumerTest;

public class Producer implements Runnable{

    private Breakfast breakfast;

    public Producer(Breakfast breakfast) {
this.breakfast = breakfast;
} @Override
public void run() {
int i = 7;
for (int i1 = 0; i1 < i; i1++) {
if (i1 %2 == 0){
this.breakfast.makeBreakfast("馒头","豆浆");
}else {
this.breakfast.makeBreakfast("面包","冷饮");
}
}
}
}

  3>消费者类:

package com.sxd.swapping.test.ProducerAndConsumerTest;

public class Consumer implements Runnable{

    private Breakfast breakfast;

    public Consumer(Breakfast breakfast) {
this.breakfast = breakfast;
} @Override
public void run() {
int i = 7;
for (int i1 = 0; i1 < i; i1++) {
System.out.println("星期"+(i1+1)+"---消费者要来吃东西了");
this.breakfast.eatBreakfast();
}
}
}

  4>线程启动主测试类:

package com.sxd.swapping.test.ProducerAndConsumerTest;

public class Test {

    public static void main(String[] args) {
Breakfast breakfast = new Breakfast();
new Thread(new Producer(breakfast)).start();
new Thread(new Consumer(breakfast)).start();
}
}

  5>展示结果:

===========================使用Lock,配合Condition的await()/signal()实现生产者消费者============================

1.早饭类,提供生产方法和消费方法

package com.sxd.swapping.test.ProducerAndConsumerTest;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
*
* Lock配合condition实现生产者消费者模式
*
* @author sxd
* @date 2019/8/6 9:08
*/
public class Condition_Breakfast { private LinkedList<String> breakfastList;//早饭资源容器 private int maxSize;//最大量早饭资源数量 自定义 private Lock lock; //锁 private Condition comsumerCondition;//满条件【即代表消费者等待队列】 private Condition producerCondition;//不满条件【即代表生产者等待队列】 //自定义 最大共享资源数量
public Condition_Breakfast(int maxSize) {
this.maxSize = maxSize;
breakfastList = new LinkedList<>();
lock = new ReentrantLock();
comsumerCondition = lock.newCondition();
producerCondition = lock.newCondition();
} public void produce(String str){
lock.lock();
try {
while (maxSize == breakfastList.size()){
System.out.println("如果早餐共享资源已经满足最大量,则进入本方法的当前线程们,进入notFullCondition的等待队列中,线程挂起");
producerCondition.await();
} breakfastList.add(str);
System.out.println("生产早饭:"+str); System.out.println("早饭已经被生产了,唤醒消费者等待队列中的线程,可以继续开始消费了");
comsumerCondition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
} public String consume(){
String str = null;
lock.lock(); try {
while (breakfastList.size() == 0 ){
System.out.println("如果早饭共享资源完全==0,就将消费者们挂起,等待生产者生产后再去唤醒消费者们");
comsumerCondition.await();
} str = breakfastList.poll();
System.out.println("消费早饭:"+str); System.out.println("早饭已经被消费了,唤醒生产者等待队列中的 线程,可以继续生产了");
producerCondition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
} return str;
} }

2.早饭类的生产者

package com.sxd.swapping.test.ProducerAndConsumerTest;

/**
* @author sxd
* @date 2019/8/6 9:26
*/
public class Condition_Producer implements Runnable { Condition_Breakfast breakfast; public Condition_Producer(Condition_Breakfast breakfast) {
this.breakfast = breakfast;
} @Override
public void run() {
int i = 7;
String threadName = Thread.currentThread().getName();
for (int i1 = 0; i1 < i; i1++) {
if (i1 %2 == 0){
this.breakfast.produce(threadName+"大馒头"+i1);
}else {
this.breakfast.produce(threadName+"大包子"+i1);
}
}
}
}

3.早饭类的消费者

package com.sxd.swapping.test.ProducerAndConsumerTest;

/**
* @author sxd
* @date 2019/8/6 9:28
*/
public class Condition_Comsumer implements Runnable{ Condition_Breakfast breakfast; public Condition_Comsumer(Condition_Breakfast breakfast) {
this.breakfast = breakfast;
} @Override
public void run() {
int i = 7;
for (int i1 = 0; i1 < i; i1++) {
this.breakfast.consume();
}
}
}

4.测试类

package com.sxd.swapping.test.ProducerAndConsumerTest;

/**
* @author sxd
* @date 2019/8/6 9:30
*/
public class Test2 { public static void main(String[] args) {
Condition_Breakfast breakfast = new Condition_Breakfast(16);
new Thread(new Condition_Producer(breakfast)).start();
new Thread(new Condition_Producer(breakfast)).start();
new Thread(new Condition_Producer(breakfast)).start();
new Thread(new Condition_Comsumer(breakfast)).start();
new Thread(new Condition_Comsumer(breakfast)).start();
new Thread(new Condition_Comsumer(breakfast)).start(); } }

5.启动效果

【多线程】java多线程实现生产者消费者模式的更多相关文章

  1. Java设计模式之生产者消费者模式

    Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...

  2. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  3. java多线程系列15 设计模式 生产者 - 消费者模式

    生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...

  4. Java多线程—阻塞队列和生产者-消费者模式

    阻塞队列支持生产者-消费者这种设计模式.该模式将“找出需要完成的工作”与“执行工作”这两个过程分离开来,并把工作项放入一个“待完成“列表中以便在随后处理,而不是找出后立即处理.生产者-消费者模式能简化 ...

  5. Java 并发编程 生产者消费者模式

    本文部分摘自<Java 并发编程的艺术> 模式概述 在线程的世界里,生产者就是生产数据的线程,消费者就是消费数据的数据.生产者和消费者彼此之间不直接通信,而是通过阻塞队列进行通信,所以生产 ...

  6. java设计模式之生产者/消费者模式

    什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者 ...

  7. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

  8. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

  9. java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

    java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了  wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...

随机推荐

  1. 转:vue-router 2.0 常用基础知识点之router.push()

    转载地址:http://www.jianshu.com/p/ee7ff3d1d93d router.push(location) 除了使用 <router-link> 创建 a 标签来定义 ...

  2. poj 2253 一条路径中的最大边 再找出最小的

    题目大意,有两只青蛙,分别在两个石头上,青蛙A想要到青蛙B那儿去,他可以直接跳到B的石头上,也可以跳到其他石头上,再从其他石头跳到B那儿,求青蛙从A到B的所有路径中最小的Frog Distance,我 ...

  3. Windows网络命令

    如何查看系统端口 Windows中要查看系统端口,可以使用netstat命令,点击开始---运行---键入cmd,打开命令提示符窗口,在命令提示符状态下键入“netstat -an”,按下回车键后就可 ...

  4. Windows下CRF++进行中文人名识别的初次尝试

    语料来自1998年1月份人民日报语料 1 语料处理 1.1 原始语料数据格式 语料中,句子已经被分词好,并且在人名后以“/”标注了“nr”表示是人名,其他非人名的分词没有进行标注 1.2 CRF++要 ...

  5. Java Socket实战之一 单线程通信基础socket

    现在做Java直接使用Socket的情况是越来越少,因为有很多的选择可选,比如说可以用spring,其中就可以支持很多种远程连接的操作,另外jboss的remoting也是不错的选择,还有Apache ...

  6. MySQL数据库之视图

    1 引言 为了简化复杂SQL语句编写,以及提高数据库安全性,MySQL数据库视图特性.视图是一张虚拟表,不在数据库中以储存的数据值形式存在.在开发中,开发者往往只对某些特定数据和所负责的特定任务感兴趣 ...

  7. [转]状态压缩dp(状压dp)

    状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...

  8. 漏洞利用查询工具sandi

    漏洞利用查询工具sandi   在渗透测试中,一旦发现漏洞,就需要查找该漏洞的利用方式.由于漏洞众多,就需要渗透测试人员从海量的漏洞信息找出可用攻击载荷.Kali Linux内置了一个查询工具sand ...

  9. netbeans启动后一会崩溃处理

    由于netbeans 默认不支持amd cpu渲染,故需要修改默认配置文件,修改后netbeans没有问题. http://stackoverflow.com/questions/34560485/n ...

  10. HDU3693 Math Teacher's Homework ---- 数位DP

    HDU3693 Math Teacher's Homework 一句话题意 给定$n, k以及m_1, m_2, m_3, ..., m_n$求$x_1 \oplus x_2 \oplus x_3 \ ...