Java实现多线程生产者消费者模式的两种方法
生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。生产者生产一个,消费者消费一个,不断循环。
第一种实现方法,用BlockingQueue阻塞队列来实现
LinkedBlockingQueue和ArrayBlockingQueue这两个类都实现了接口BlockingQueue,我们可以用这两个阻塞队列来处理多线程间的生产者消费者问题。
1.LinkedBlockingQueue:
主要方法:
- put(E e): 这个方法用于向BlockingQueue中插入元素,如果BlockingQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里有空间再继续。
- E take(): 这个方法用于取走BlockingQueue里面排在首位的对象,如果BlockingQueue为空,则调用线程被阻塞,进入等待状态,直到BlockingQueue有新的数据被加入。
实现生产者消费者问题
ConsumerQueue.java 消费者类
public class ConsumerQueue implements Runnable {
private final BlockingQueue conQueue;
public ConsumerQueue(BlockingQueue conQueue) {
this.conQueue = conQueue;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
System.out.println("消费者消费的商品编号为 :" + conQueue.take());
Thread.sleep(300); // 在这里sleep是为了看的更加清楚些
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
ProducerQueue.java 生产者类
public class ProducerQueue implements Runnable {
private final BlockingQueue proQueue;
public ProducerQueue(BlockingQueue proQueue) {
this.proQueue = proQueue;
}
int task = 1;
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
proQueue.put(task);
System.out.println("生产者生产的商品编号为 : " + task);
task++;
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
SharedQueue.java 启动
public class SharedQueue {
public static void main(String[] args) {
/*
* 1.ArrayBlockingQueue必须指定队列大小,是有界的
* 2.LinkedBlockingQueue可以不指定队列大小,无界,默认大小为Integer
* .MAX_VALUE;也可以指定队列大小,变成有界的
*/
// BlockingQueue blockingQueue = new ArrayBlockingQueue(10);
BlockingQueue sharedQueue = new LinkedBlockingQueue(2); // 定义了一个大小为2的队列
Thread pro = new Thread(new ProducerQueue(sharedQueue));
Thread con = new Thread(new ConsumerQueue(sharedQueue));
pro.start();
con.start();
}
}
第二种:通过java提供的等待唤醒机制来解决 多线程常用函数:
getThread.java 消费者类
public class getThread implements Runnable {
private Student student;
public getThread(Student student) {
this.student = student;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (student) {
// 消费者没用数据就等待
while (!student.flag) {
try {
student.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(student.name + "------" + student.age);
// 消费完了就置为false没有
student.flag = false;
student.notify();
}
}
}
}
setThread.java 生产类
public class setThread implements Runnable {
private Student student;
private int x = 0;
public setThread(Student student) {
this.student = student;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (student) {
// 生产者有数据就等待,修改为while,保证每次wait()后再notify()时先再次判断标记。
while(student.flag){
try {
student.wait(); // 等待,会同时释放锁;将来醒过来的时候,就是在这里醒过来的。
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (x % 2 == 0) {
student.name = "AAA";
student.age = 22;
} else {
student.name = "BBB";
student.age = 24;
}
x++;
//修改标记
student.flag = true;
student.notify();
}
}
}
}
学生资源类
public class Student {
//同一个包下可以访问
String name;
int age;
boolean flag; // 默认情况是没有数据,如果有就是true
}
Main
public class StudentDemo {
public static void main(String[] args){
Student student = new Student();
setThread st = new setThread(student);
getThread gt = new getThread(student);
Thread t1 = new Thread(st);
Thread t2 = new Thread(gt);
t1.start();
t2.start();
}
}
运行结果:

Java实现多线程生产者消费者模式的两种方法的更多相关文章
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- java 多线程并发系列之 生产者消费者模式的两种实现
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...
- java实现多线程生产者消费者模式
1.概念 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消 ...
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- Java构造和解析Json数据的两种方法详解二
在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Jso ...
- Java构造和解析Json数据的两种方法详解二——org.json
转自:http://www.cnblogs.com/lanxuezaipiao/archive/2013/05/24/3096437.html 在www.json.org上公布了很多JAVA下的jso ...
- Java构造和解析Json数据的两种方法详解一——json-lib
转自:http://www.cnblogs.com/lanxuezaipiao/archive/2013/05/23/3096001.html 在www.json.org上公布了很多JAVA下的jso ...
- Java执行shell脚本并返回结果两种方法的完整代码
Java执行shell脚本并返回结果两种方法的完整代码 简单的是直接传入String字符串,这种不能执行echo 或者需要调用其他进程的命令(比如调用postfix发送邮件命令就不起作用) 执行复杂的 ...
- DES加密 java与.net可以相互加密解密两种方法
DES加密 java与.net可以相互加密解密两种方法 https://www.cnblogs.com/DrWang/archive/2011/03/30/2000124.html sun.misc. ...
随机推荐
- 以EntifyFramework DBFirst方式访问SQLite数据库
前面一直在找EF Code First方式来访问SQLite数据库,后面得出的结论是SQLite不支持 Code First, 虽然有非官方的库SQLite.CodeFirst可以使用,但一直没搞成功 ...
- sql语句中包含引号处理方法
1. 背景 在使用Python脚本向数据库导入日志文件时候,突然报错. 2. 解决思路 查看messages文件,发现有一条语句里包含单引号. 查看sql语句,是使用单引号标注str类型. 3. 得出 ...
- 通过DB13备份SystemDB
配置systemdb capital user name:SYSTEM save -back Save 现在可以通过DB13备份SystemDB Done. Congratulations!
- c# 使用序列化
- flask+uwsgi+supervisor部署流程
背景: 小鱼最近搞了个工程,python用的2.7(用3也可以),后端使用的是flask,服务器用的linux,使用 flask+uwsgi+supervisor部署 ,查阅相关博客.调试.实操,已经 ...
- 能ping通Linux但是ssh连不上问题解决方法
问题:能ping通Linux服务器 但是ssh连不上 <Linux redhat AS4 版本> 解决方法这个问题花了我20分钟去查资料,网上写的解决方法也是五花八门,不过,总算解决了, ...
- tslint.json的配置项说明
tslint.json的配置项说明 extends: 内设配置项名称 rules: 规则 { //ts专用 adjacent-overload-signatures : true, // Enfo ...
- Redis的下载、安装及启动
一.下载Redis 1. redis 的下载路径 https://pan.baidu.com/s/1tdMzOlcTlFC7Z3a3I_59hQ 提取码:5tgy 二.安装Redis cd到当前解压目 ...
- HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9
/* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问 ...
- JAVA的选择结构(二)
1.switch选择结构: 语法: switch (key) { ...