Java的多线程实现生产/消费模式

在Java的多线程中,我们经常使用某个Java对象的wait(),notify()以及notifyAll() 方法实现多线程的通讯,今天就使用Java的多线程实现生产/消费模式,需求如下:

  • 线程A ProductThread 继承Thread 实现生产数据
  • 若线程共享的数据不为NULL,则生产线程进入等待状态
  • 线程B CustomThread 继承Thread 实现消费数据(输出到控制台)
  • 当线程共享数据为NULL的时候,进入等待状态
  • 线程B 消费完数据之后,通知线程A开始生产数据

数据共享单元

package com.zhoutao.demo.thread.notify;

public class ValueFactory {
// 为了方便阅读代码,这里直接使用了共有的字符串类保存线程共有数据
public static String value = null;
}

生产者

生产者对象

package com.zhoutao.demo.thread.notify;

public class Product {
// 线程锁对象,由主线层提供
private String lock; public Product(String lock) {
this.lock = lock;
} public void setObject() throws InterruptedException {
// 获取锁对象
synchronized (lock) {
// 如果数据存在, 那么生产线程进入wait
if (ValueFactory.value != null) {
lock.wait();
}
// 消费者线程通知生产者线程继续执行
String randomStr = String.valueOf(Math.random());
// 设置数据到线程共享对象中
ValueFactory.value = randomStr;
System.out.println("Put Value = " + randomStr);
// 生产数据完成,通知消费者线程消费
lock.notify();
}
}
}

生产者线程

  public class ProductThread extends Thread {
private Product product; public ProductThread(Product product) {
this.product = product;
} @Override
public void run() {
try {
// 不停地生产数据
while (true) {
product.setObject();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

消费者

消费者对象和生产者对象非常的类似,如果数据不存在,则等待,数据存在则消费打印,并将数据置为NULL,同时通知生产者线程生产数据

package com.zhoutao.demo.thread.notify;

import javax.xml.stream.util.XMLEventAllocator;
import java.util.concurrent.TimeUnit; public class Custom { private String lock; public Custom(String lock) {
this.lock = lock;
} public void getObject() throws InterruptedException {
synchronized (lock) {
if (ValueFactory.value == null) {
lock.wait();
}
TimeUnit.SECONDS.sleep(1);
System.out.println("Get Value = " + ValueFactory.value);
ValueFactory.value = null;
lock.notify();
}
}
}

消费者线程

 public class CustomThread extends Thread {
private Custom custom; public CustomThread(Custom custom) {
this.custom = custom;
} @Override
public void run() {
try {
while (true) {
custom.getObject();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

主线程

在生产者和消费者均创建完成后,我们尝试创建并启动两个线程,观察数据.

public class Demo {

  public static void main(String[] args) {
String lockStr = "ABC"; Product product = new Product(lockStr);
Custom custom = new Custom(lockStr);
// 创建线程
ProductThread pThread = new ProductThread(product);
CustomThread cThread = new CustomThread(custom); pThread.start();
cThread.start();
}

数据记录

可以非常明显的观察到,生产者PUT数据后,通知消费者,消费者GET数据后,置空数据,再通知生产者生产数据,这样就完成了简单的生产/消费模式,当然可以使用Java的栈数据结构来实现pop() 以及push() 更加的完善。

Put Value = 0.9451520952786396
Get Value = 0.9451520952786396
Put Value = 0.9103106225308949
Get Value = 0.9103106225308949
Put Value = 0.030296348285276054
Get Value = 0.030296348285276054
Put Value = 0.7746272403879736
Get Value = 0.7746272403879736

Java的多线程实现生产/消费模式的更多相关文章

  1. NDK学习笔记-多线程与生产消费模式

    在做NDK开发的时候,很多情况下都是需要使用多线程的,一方面是提高程序运行效率,另一方面就是防止主线程阻塞 C的多线程 在C语言里,可以通过对于POSIX标准的运用,使得C语言执行多线程 提高程序的执 ...

  2. 使用Condition实现多线程之间调用(生产消费模式)

    一,object 类的wait(),notify()和notifyAll() Java 线程类也是一个object 类,它的实例都继承自java.lang.Thread 或其子类.wait(),not ...

  3. Java基础--多线程的方方面面

    1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 ...

  4. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  5. 异步简析之BlockingCollection实现生产消费模式

    目前市面上有诸多的产品实现队列功能,比如Redis.MemCache等... 其实c#中也有一个基础的集合类专门用来实现生产/消费模式 (生产模式还是建议使用Redis等产品) 下面是官方的一些资料和 ...

  6. java基础-多线程应用案例展示

    java基础-多线程应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.两只熊,100只蜜蜂,蜜蜂每次生产的蜂蜜量是1,罐子的容量是30,熊在罐子的蜂蜜量达到20的时候 ...

  7. 使用C#的泛型队列Queue实现生产消费模式

    本篇体验使用C#的泛型队列Queue<T>实现生产消费模式. 如果把生产消费想像成自动流水生产线的话,生产就是流水线的物料,消费就是某种设备对物料进行加工的行为,流水线就是队列. 现在,要 ...

  8. 【Java】多线程入门

    Java多线程学习(入门) 前言 目前对于线程的了解仅仅停留在学习python的threading库,很多线程的概念没有真正弄清楚,所以选择来系统性的学习多线程.那么这次选择的是Java的多线程学习, ...

  9. Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

随机推荐

  1. Java基础系列-ArrayList

    原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...

  2. 第15章 时间常数字符串比较 - IdentityModel 中文文档(v1.0.0)

    在比较安全上下文中的字符串(例如比较键)时,应尽量避免泄漏时序信息. 该TimeConstantComparer类可以帮助: var isEqual = TimeConstantComparer.Is ...

  3. Android之Realm详解

    文章大纲 一.Realm介绍二.Realm实战三.Realm官方文档四.项目源码下载五.参考文章   一.Realm介绍 1. 什么是Realm   Realm 是一个手机数据库,是用来替代 SQli ...

  4. MARKY一下。

    答:其实RUP整个流程都在讲SQA.业界常见的模型,譬如CMM/CMMI,六西格玛,ISO9000,RUP,它们做的基本上是同一件事情--都是在做流程改进,都在做质量控制,但是各自的侧重点不一样.像R ...

  5. Linux集群时间同步方法

    方法1.ntp  平滑同步时间 (一)确认ntp的安装 1)确认是否已安装ntp [命令] rpm –qa | grep ntp 若只有ntpdate而未见ntp,则需删除原有ntpdate.如: n ...

  6. mpvue小程序开发之 wx.getUserInfo获取用户信息授权

    一.背景 在使用美团的mpvue2.0框架搭建起小程序项目后,做获取用户信息时遇到一些问题:微信小程序更新api后,获取用户信息只能通过button上的绑定方法 来获取用户信息,vue上方法绑定不能直 ...

  7. Spring 对Controller异常的统一处理

    对于Controller的异常处理,分为两种,一种是对已知的异常处理,一种是未知的异常处理 1.定义自定义异常类 /** * @author hzc * */ public class UserNot ...

  8. 【Dubbo篇】--Dubbo框架的使用

    一.前述 Dubbo是一种提供高性能,透明化的RPC框架.是阿里开源的一个框架. 官网地址:http://dubbo.io/ 二.架构 组件解释: Provider: 提供者.发布服务的项目.Regi ...

  9. qml demo分析(objectlistmodel-自定义qml数据)

    一.效果展示 如图1所示,是一个ListView窗口,自定义了文本内容和项背景色. 图1 ListView 二.源码分析 代码比较简单,主要使用了QQmlContext类的setContextProp ...

  10. 分布式基础通信协议:paxos、totem 和 gossip(转载)

    背景: 在分布式中,最难解决的一个问题就是多个节点间数据同步问题.为了解决这样的问题,涌现出了各种奇思妙想.只有在解决了如何进行信息同步的基础之上才衍生出形形色色的应用.这里开始介绍几种分布式通信协议 ...