Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
Java数据结构之---Queue队列
队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。
队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。最简单的例子就是我们平时的排队,先进先出。
顺序队列的存储结构
下图是一个有6个存储空间的顺序队列的动态示意图,图中front指示队头,rear指示队尾。

~顺序队列的假溢出现象
假溢出是由于队尾rear的值和队头front的值不能由所定义数组下界值自动转为数组上界值而产生的。因此,解决的方法是把顺序队列所使用的存储空间构造成一个逻辑上首尾相连的循环队列( Circular Queue)。
~解决方法
当rear和front达到maxSize-1后,再加1就自动到0。这样,就不会出现顺序队列数组的头部已空出许多存储空间,但队尾却因数组下标越界而引起溢出的假溢出问题。这里在代码里面会详细解释~

在操作完成后,该队列中会有两个空格没有数据元素保存,造成资源浪费,这就是假溢出现象。
//==========================
//使用自定义的queue接口
//队列接口
public interface Queue { // 入队
public void append(Object obj) throws Exception; // 出队
public Object delete() throws Exception; // 获得对头元素
public Object getFront() throws Exception; // 判断是否为空
public boolean isEmpty(); }
Queue interface
//循环链表的具体实现
/*
* 循环顺序队列
*/
public class CircleSequenceQueue implements Queue { static final int defaultsize = 10;// 默认队列的长度
int front; // 对头
int rear; // 队尾
int count;// 统计元素个数的计数器
int maxSize; // 队的最大长度
Object[] queue; // 队列,使用数组实现 // 默认构造
public CircleSequenceQueue() {
init(defaultsize);
} public CircleSequenceQueue(int size) {
// 通过给定长度进行构造
init(size);
} public void init(int size) {
maxSize = size;
front = rear = 0;
count = 0;
queue = new Object[size];
} @Override
public void append(Object obj) throws Exception {
// TODO Auto-generated method stub
if (count > 0 && front == rear) {
throw new Exception("队列已满");
}
// 队尾插入数据
queue[rear] = obj;
// 通过这种方法让对标索引值不停的重复!!!
rear = (rear + 1) % maxSize;
count++;
} @Override
public Object delete() throws Exception {
// TODO Auto-generated method stub
if (isEmpty()) {
throw new Exception("队列为空");
}
// 去除对头的元素,同时修改对头的索引值
Object obj = queue[front];
// 对头索引值,一样通过+1驱魔运算来实现循环索引效果
front = (front + 1) % maxSize;
count--;
return obj;
} @Override
public Object getFront() throws Exception {
// TODO Auto-generated method stub
if (!isEmpty()) {
return queue[front];
} else {
// 对为空返回null
return null;
}
} @Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return count == 0;
} }
//得到循环链表后,对其进行应用,之类主要是模拟卖票窗口
· 实例:使用顺序循环队列和多线程实现一个排队买票的例子。
· 生产者(等候买票)
· 消费者 (买票离开)
//代码的分割线,使用生产者消费者模式进行设计,主要是使用同步机制
//卖票窗口
public class WindowQueue { // 卖票的队列默认长度10
int maxSize = 10;
CircleSequenceQueue queue = new CircleSequenceQueue(maxSize);
// 用来统计卖票的数量,一天最多卖100张票?
int num = 0;
boolean isAlive = true; // 判断是否继续卖票 // 排队买票,使用同步机制
public synchronized void producer() throws Exception {
// count队列中的元素个数,如果该值小于maxSize则可以买票
if (queue.count < maxSize) {
queue.append(num++); // 等待买票的数量+1
System.out.println("第" + num + "个客户排队等待买票");
this.notifyAll(); // 通知卖票线程可以卖票了
}
// 如果满了
else {
try { System.out.println("队列已满...请等待");
this.wait(); // 队列满时,排队买票线程等待,其实等待卖票队伍里面离开一个人后来唤醒自己 } catch (Exception e) {
e.printStackTrace();
}
}
} // 排队卖票,使用同步机制
public synchronized void consumer() throws Exception {
// count队列中的元素个数,如果该值大于0,则说明有票可以继续卖票
if (queue.count > 0) { Object obj = queue.delete();
// 第几个人买到票了
int temp = Integer.parseInt(obj.toString());
System.out.println("第" + (temp + 1) + "个客户排队买到票离开队列");
// 如果当前队列为空,并且卖出票的数量的大于等于100说明卖票要结束
if (queue.isEmpty() && this.num >= 100) {
this.isAlive = false;
}
// 排队队伍离开一个人,可以进来一个人进行买票了。
this.notifyAll(); // 通知买票线程可以买了,唤醒买票线程
}
// 如果满了
else {
try { System.out.println("队列已空...请进入队伍准备买票");
this.wait();// 队列空时,排队卖票线程等待,其实等待买票队伍里面进来一个人后买票来唤醒自己 } catch (Exception e) {
e.printStackTrace();
}
}
}
}
//下面的两个类是生产者与消费者的具体实现,实现runnable接口
//买票者
public class Producer implements Runnable {
// 买票窗口
WindowQueue queue;
// 保证和消费者使用同一个对象
public Producer(WindowQueue queue) {
this.queue = queue;
}
@Override
public void run() {
// TODO Auto-generated method stub
//
while (queue.num < 100) {
try {
//执行买票,消费者
queue.producer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//卖票者
public class Consumer implements Runnable {
WindowQueue queue; // 保证卖票与买票同步
public Consumer(WindowQueue queue) {
this.queue = queue;
} @Override
public void run() {
// 判断是否可以继续卖票
while (queue.isAlive) {
try {
// 卖票
queue.consumer(); } catch (Exception e) {
e.printStackTrace();
}
}
}
}
//测试。。。。。
public class Test {
public static void main(String[] args) throws Exception {
/*
* CircleSequenceQueue queue = new CircleSequenceQueue();
* queue.append("a"); queue.append("b"); queue.append("c");
* queue.append("d"); queue.append("e");
*
* while (!queue.isEmpty()) { System.out.print(queue.delete() + " "); }
*/
// 卖票与买票模拟,使用同一个窗口对象
WindowQueue queue = new WindowQueue();
// 生产者
Producer P = new Producer(queue);
// 消费者
Consumer c = new Consumer(queue);
// 排队买票线程
Thread pThread = new Thread(P);
// 买票线程
Thread cThread = new Thread(c);
pThread.start(); // 开始排队买票
cThread.start(); // 卖票
}
}
Test Code
Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用的更多相关文章
- Java数据结构和算法(五)——队列
前面一篇博客我们讲解了并不像数组一样完全作为存储数据功能,而是作为构思算法的辅助工具的数据结构——栈,本篇博客我们介绍另外一个这样的工具——队列.栈是后进先出,而队列刚好相反,是先进先出. 1.队列的 ...
- 自己动手实现java数据结构(四)双端队列
1.双端队列介绍 在介绍双端队列之前,我们需要先介绍队列的概念.和栈相对应,在许多算法设计中,需要一种"先进先出(First Input First Output)"的数据结构,因 ...
- Java数据结构——用双端链表实现队列
//================================================= // File Name : LinkQueue_demo //---------------- ...
- Java数据结构和算法之栈与队列
二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为 ...
- Java数据结构和算法(十四)——堆
在Java数据结构和算法(五)——队列中我们介绍了优先级队列,优先级队列是一种抽象数据类型(ADT),它提供了删除最大(或最小)关键字值的数据项的方法,插入数据项的方法,优先级队列可以用有序数组来实现 ...
- 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?
多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...
- java多线程15 :wait()和notify() 的生产者/消费者模式
什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...
- java 数据结构 队列的实现
java 数据结构队列的代码实现,可以简单的进行入队列和出队列的操作 /** * java数据结构之队列的实现 * 2016/4/27 **/ package cn.Link; import java ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现
本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...
随机推荐
- 1JavaScript简介
文档对象模型(DOM,Document Object Model)是针对XML但经过扩展用于HTML的应用程序编程接口(API,Application Programming Interface). ...
- JDBC详解(转)
原文链接:http://blog.csdn.net/cai_xingyun/article/details/41482835 什么是JDBC? Java语言访问数据库的一种规范,是一套API JDBC ...
- (转)百度编辑器java使用
说在前面 工作中会遇到很多需要使用富文本编辑器的地方,比如我现在发布这篇文章离不开这个神器,而且现在网上编辑器太多了.记得之前,由于工作需要自己封装过一个编辑器的公共插件,是用ckeditor改版的, ...
- iOS开发UI篇—iPad和iPhone开发的比较
一.iPad简介 1.什么是iPad 一款苹果公司于2010年发布的平板电脑 定位介于苹果的智能手机iPhone和笔记本电脑产品之间 跟iPhone一样,搭载的是iOS操作系统 2.iPad的市场情况 ...
- 解决点击cell时,UILabel的背景颜色消失的问题
-(void)setSelected:(BOOL)selected animated:(BOOL)animated{ [super setSelected:selected animated:anim ...
- JAVASE02-Unit03: 日期操作 、 集合框架
Unit03: 日期操作 . 集合框架 java.util.Date package day03; import java.util.Date; /** * java.util.Date * Date ...
- GCD的简单用法
/* 创建一个队列用来执行任务,TA属于系统预定义的并行队列即全局队列,目前系统预定义了四个不同运行优先级的全局队列,我们可以通过dispatch_get_global_queue来获取它们 四种优先 ...
- 简介 jCanvas:当 jQuery遇上HTML5 Canvas
https://github.com/caleb531/jcanvas HTML5 可以直接在你的网页中使用 <canvas> 元素及其相关的 JavaScript API绘制的图形. 在 ...
- lua 面向对象编程类机制实现
lua no class It is a prototype based language. 在此语言中没有class关键字来创建类. 现代ES6, 已经添加class类. prototype bas ...
- Android四大核心组件之Service
实验内容 启动Service 绑定Service 与Service进行通信 实验要求 启动Service 绑定Service 与Service进行通信 实验步骤 Service概述 Service通常 ...