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. ...
随机推荐
- SQL Server2008分离数据库
1.右击数据库 2.Tasks 3.点击Detach 4.选取Drop Connections-->点击确定 5.开启本地数据库默认存储路径C:\Program Files\Microsoft ...
- DotNet 使用阿里云媒体转码服务
公司项目中一部分文件放到了阿里云 OSS 上,其中有些音频文件是 amr 类型的,在后期使用的时候比较麻烦,所以需要转换成 mp3 的文件,方便以后使用.本来想使用 ffmpeg 处理,但由于文件都存 ...
- vs2015工程转化为vs2010
转换的步骤如下: (1)将工程是.sln用记事本打开后,更换以下信息如下: Microsoft Visual Studio Solution File, Format Version 11.00 ...
- ORACLE大对象存储
--创建有大对象字段的一张表 create table test001 ( fname varchar2(50), content blob ) select * from ...
- C++ 解决文件重复包含
// 如果zzz没有定义就定义zzz,然后执行下面的代码,定义了就不执行 #if !defined(zzz) #define zzz struct PPoint { int x; int y; }; ...
- 发现一个对列排版挺好用的命令:column
help [root@hdpool1 tmp]# column -h Usage: column [options] [file ...] Options: -c, --columns <wid ...
- GNU/Linux 介绍
在了解Linux之前要先了解什么是GNU / GNU官方解释? GNU是一个自由软件操作系统.就是说,它尊重其使用者的自由.GNU操作系统包括GNU软件包(专门由GNU工程发布的程序)和由第三方发布的 ...
- c# 虚属性
- Kotlin重新学习及入门示例
在2017和2018其实已经对Kotlin的基础语法进行了一些学习,但是!!如今已经是2019年,中间间断时间已经很长了,所以准备接下来从0再次出发深入系统完整的来审视一下该语言,毕境如今它的地位是越 ...
- jstack、jmc、jhat工具使用详解
jstack: 在上一次[https://www.cnblogs.com/webor2006/p/10669472.html]jcmd中也可以获取线程的堆栈信息,回顾一下: 其实在JDK中还有另一个专 ...