Java的多线程实现生产/消费模式
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的多线程实现生产/消费模式的更多相关文章
- NDK学习笔记-多线程与生产消费模式
在做NDK开发的时候,很多情况下都是需要使用多线程的,一方面是提高程序运行效率,另一方面就是防止主线程阻塞 C的多线程 在C语言里,可以通过对于POSIX标准的运用,使得C语言执行多线程 提高程序的执 ...
- 使用Condition实现多线程之间调用(生产消费模式)
一,object 类的wait(),notify()和notifyAll() Java 线程类也是一个object 类,它的实例都继承自java.lang.Thread 或其子类.wait(),not ...
- Java基础--多线程的方方面面
1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 ...
- java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...
- 异步简析之BlockingCollection实现生产消费模式
目前市面上有诸多的产品实现队列功能,比如Redis.MemCache等... 其实c#中也有一个基础的集合类专门用来实现生产/消费模式 (生产模式还是建议使用Redis等产品) 下面是官方的一些资料和 ...
- java基础-多线程应用案例展示
java基础-多线程应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.两只熊,100只蜜蜂,蜜蜂每次生产的蜂蜜量是1,罐子的容量是30,熊在罐子的蜂蜜量达到20的时候 ...
- 使用C#的泛型队列Queue实现生产消费模式
本篇体验使用C#的泛型队列Queue<T>实现生产消费模式. 如果把生产消费想像成自动流水生产线的话,生产就是流水线的物料,消费就是某种设备对物料进行加工的行为,流水线就是队列. 现在,要 ...
- 【Java】多线程入门
Java多线程学习(入门) 前言 目前对于线程的了解仅仅停留在学习python的threading库,很多线程的概念没有真正弄清楚,所以选择来系统性的学习多线程.那么这次选择的是Java的多线程学习, ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
随机推荐
- Netty源码—四、事件处理
前面经过channel初始化.注册,所需要的数据结构(epoll_event)基本上准备好了,serverSocket也处于监听状态,可以接收来自客户端的请求了.NioServerSocketChan ...
- 从源码解读线程(Thread)和线程池(ThreadPoolExecutor)的状态
线程是比进程更加轻量级的调度执行单位,理解线程是理解并发编程的不可或缺的一部分:而生产过程中不可能永远使用裸线程,需要线程池技术,线程池是管理和调度线程的资源池.因为前不久遇到了一个关于线程状态的问题 ...
- C# 将object对象转换为实体对象
C# 将object对象转换为实体对象.一共两种方法. 第一种方法,代码如下: /// <summary> /// 将object对象转换为实体对象 /// </summary> ...
- Cenots7下安装运行.NET Core、MicroSoft SQL Server 2019 preview 的基础实践
一:概要 适应人群:.Net初学者.想了解.Net Core在Linux系统中的运行环境搭建者.初次且想在linux上应用.Net Core开发应用程序者: 基础技能:了解.NET基础开发技能者.有一 ...
- iOS客户端图片智能裁剪
 概述 所谓智能裁剪其实就是按照指定尺寸裁剪或显示出包含图片核心特征的区域,目前很多智能裁剪都是在服务器端做的,在客户端需要访问时直接裁剪放到Redis或者提前裁剪好以备访问.但是找了一圈直接在iO ...
- 知识科普:IM聊天应用是如何将消息发送给对方的?(非技术篇)
1.引言 沟通是人类的最基本需求,复杂多变的沟通内容.沟通方式,正是人类文明之所以如此璀璨的关键所在. 在自然界中,要完成一件事情的沟通,我们可以直接通过声音传递给对方,这是再平常不过的事了(靠“ ...
- SpringBoot 2.X集成Hive-jdbc 3.1.1
最近公司有一个需求,需求的内容是根据用户页面选择的参数条件查询Hive,数量量大致是300万以内,要求3秒响应.使用的其它的技术就不要说了,先说说SpingBoot集成Hive-jdbc吧,网上虽然有 ...
- C语言随机数使用方法
随机数在编程中还是有所应用,最近从网上学习到这方面一点知识,想把它写下来.一.使用随机数所需要的头文件和函数: 头文件:cstdlib(C++ 的 standard libraray) ...
- 关于 Docker 镜像的操作,看完这篇就够啦 !(下)
紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...
- 使用nvm管理node不同版本,安装,环境配置,切换不同版本的node版本
文章包含以下内容: 一.下载地址 二.nvm-noinstall.zip安装 三.nvm-setup.zip安装 四.测试安装以及使用 一.下载地址 https://github.com/coreyb ...