• 队列是一种特殊的线性表；...顺序队列的实现： #ifndef _SEQQUEUE_H_ #define _SEQQUEUE_H_ typedef void SeqQueue;//数据封装 SeqQueue* SeqQueue_Create(int capacity);//顺序队列，capacity表示队列的
队列是一种特殊的线性表；
队列仅在线性表的两端进行操作；
队头：取出元素的一端； 队尾：插入元素的一端；
顺序队列的实现：
#ifndef _SEQQUEUE_H_
#define _SEQQUEUE_H_
typedef void SeqQueue;//数据封装
SeqQueue* SeqQueue_Create(int capacity);//顺序队列，capacity表示队列的大小容量；
void SeqQueue_Destroy(SeqQueue* queue);
void SeqQueue_Clear(SeqQueue* queue);//
int SeqQueue_Append(SeqQueue* queue, void* item);//插入操作，插入一个新元素
void* SeqQueue_Retrieve(SeqQueue* queue);//取回操作，取回已经存在的元素
int SeqQueue_Length(SeqQueue* queue);
int SeqQueue_Capacity(SeqQueue* queue);
#endif

#include "SeqList.h"//代码复用的思想，因此需要包含此头文件
#include "SeqQueue.h"
SeqQueue* SeqQueue_Create(int capacity) // O(1)
{
return SeqList_Create(capacity);
}
void SeqQueue_Destroy(SeqQueue* queue) // O(1)
{
SeqList_Destroy(queue);
}
void SeqQueue_Clear(SeqQueue* queue) // O(1)
{
SeqList_Clear(queue);
}
int SeqQueue_Append(SeqQueue* queue, void* item) // 只能在队尾部插入//O(1)
{
return SeqList_Insert(queue, item, SeqList_Length(queue));
}
void* SeqQueue_Retrieve(SeqQueue* queue) // O(n)//从队头取一个元素
{
return SeqList_Delete(queue, 0);
}
{
return SeqList_Get(queue, 0);
}
int SeqQueue_Length(SeqQueue* queue) // O(1)
{
return SeqList_Length(queue);
}
int SeqQueue_Capacity(SeqQueue* queue) // O(1)
{
return SeqList_Capacity(queue);
}

#include <stdio.h>
#include <stdlib.h>
#include "SeqQueue.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[])
{
SeqQueue* queue = SeqQueue_Create(20);
int a[10] = {0};
int i = 0;
for(i=0; i<10; i++)
{
a[i] = i + 1;
SeqQueue_Append(queue, a + i);
}
printf("Length: %d\n", SeqQueue_Length(queue));
printf("Capacity: %d\n", SeqQueue_Capacity(queue));
while( SeqQueue_Length(queue) > 0 )
{
printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue));
}
SeqQueue_Destroy(queue);return 0;
}
链式队列的实现:
#endif
#include <malloc.h>
{
void* item;
{
}
{
}
{
{
}
}
{
int ret = (item != NULL) && (node != NULL);
if( ret )
{
node->item = item;

}
if( !ret )
{
free(node);
}
return ret;
}
{
void* ret = NULL;
if( node != NULL )
{
ret = node->item;
free(node);
}
return ret;
}
{
void* ret = NULL;
if( node != NULL )
{
ret = node->item;
}
return ret;
}
{
}

#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[])
{
int a[10] = {0};
int i = 0;
for(i=0; i<10; i++)
{
a[i] = i + 1;
}
{
}
}
队列是一种特殊的线性表；
队列只允许在头部和尾部进行操作；
队列有顺序实现和链式实现两种实现方式；


展开全文
• java中堆栈和队列的实现方式队列和栈区别：队列先进先出，栈先进后出。 队列的实现—利用Queue接口 堆栈的实现—利用Deque接口 使用ArrayDeque类实例化队列和栈 队列的实现—利用Queue接口：该接口在java5中新增加，...
java中堆栈和队列的实现方式

队列和栈区别：队列先进先出，栈先进后出。

队列的实现—利用Queue接口
堆栈的实现—利用Deque接口
使用ArrayDeque类实例化队列和栈
队列的实现—利用Queue接口：

该接口在java5中新增加，用以支持队列的常见操作。该接口扩展了java.util.Collection接口。 接口声明：

public interface Queue<E>extends Collection<E>  

主要方法：除了基本的 Collection 操作外，队列主要提供的插入、移除和检查操作。并且每个方法都存在两种形式：一种抛出异常（操作失败时），另一种返回一个特殊值（null 或 false，具体取决于操作）。如下图：

操作
抛出异常
返回特殊值
插入
offer(e)
移除
remove()
poll()
检查
element()
peek()
其中有返回特殊值的三个方法是Queue接口特意为队列实现的，因此我们应使用这三个方法。

Queue 实现通常不允许插入 null 元素，尽管某些实现（如 LinkedList）并不禁止插入 null。即使在允许 null 的实现中，也不应该将 null 插入到 Queue 中，因为 null 也用作 poll 方法的一个特殊返回值，表明队列不包含元素。 实例化队列：可以使用LinkedList类实现了Queue接口，因此我们可以把LinkedList当成Queue来用。

//@xue
import java.util.Queue;

public class Test {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<String> ();
queue.offer("x");
queue.offer("u");
queue.offer("e");
while(!queue.isEmpty()){
System.out.print(queue.poll()+" ");
}
}
}

堆栈的实现—利用Deque接口:

接口声明：

public interface Deque<E>extends Queue<E>

此接口扩展了 Queue 接口。一个线性 collection，支持在两端插入和移除元素。名称 deque 是“double ended queue（双端队列）”的缩写，通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制，但此接口既支持有容量限制的双端队列，也支持没有固定大小限制的双端队列。 主要方法：其用于堆栈的主要方法如下图：

操作
堆栈方法
插入
push(e)
移除
pop()
检查
peek()

//@xue
import java.util.Deque;

public class Test {
public static void main(String[] args) {
stack.push("x");
stack.push("u");
stack.push("e");
while(!stack.isEmpty()){
System.out.print(stack.pop());
}
}
}

使用ArrayDeque类实例化队列和栈：

接口声明：

public class ArrayDeque<E>
extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable

该类是Deque接口的大小可变数组的实现。数组双端队列没有容量限制；它们可根据需要增加以支持使用。它们不是线程安全的；在没有外部同步时，它们不支持多个线程的并发访问。禁止 null 元素。此类很可能在用作堆栈时快于 Stack，在用作队列时快于 LinkedList。 主要方法：

操作
队列方法
插入
offer(e)
移除
poll()
检查
peek()
操作
堆栈方法
插入
push(e)
移除
pop()
检查
peek()
实例化堆栈和队列：可以new一个ArrayDeque的对象，既可以当队列由可以当队列来使用。
堆栈的实例：

//@xue
import java.util.ArrayDeque;

public class Test {
public static void main(String[] args) {
ArrayDeque<String> stack = new ArrayDeque<String> ();
stack.push("x");
stack.push("u");
stack.push("e");
while(!stack.isEmpty()){
System.out.print(stack.pop());
}
}
}

队列的实例：

//@xue
import java.util.ArrayDeque;

public class Test {
public static void main(String[] args) {
ArrayDeque<String> queue = new ArrayDeque<String> ();
queue.offer("x");
queue.offer("u");
queue.offer("e");
while(!queue.isEmpty()){
System.out.print(queue.poll()+" ");
}
}
}

关于 Queue的API ，参考 这儿
关于 Deque 的API，参考 这儿
关于 ArrayDeque的API，参考这儿

展开全文
• 队列的概念： 1、是队列结构的中间件 2、消息放入后不需要立即处理 3、由订阅者/消费者按顺序处理 队列原理： 也是解耦的原理：业务系统和队列处理系统没有关系 一个写（业务系统），一个读（队列管理系统）。 写的...
队列的概念：
1、是队列结构的中间件
2、消息放入后不需要立即处理
3、由订阅者/消费者按顺序处理
队列原理：

也是解耦的原理：业务系统和队列处理系统没有关系
一个写（业务系统），一个读（队列管理系统）。
写的只管往队列里写，别的不用操心，读的能不能读完和写的也没有关系
同样，读的只管从队列里往外读，来活儿就干，没活儿歇着
应用场景：
冗余：持久化的存储在队列中，后续由订单处理程序获取，处理完成之后，在把这条记录进行删除
解耦：是解这2套系统（业务和队列处理），我们平常做的都是一套系统的。入队和出队的系统没有直接的关系，其中一套蹦了，另一套系统不会受影响，因为中间隔了个队列
流量削锋：秒杀和抢购。流量剧增，配合缓存使用消息队列（就是限制下，如 只允许10个，队列里存10个之后就不存了，在来就提示秒杀结束）
异步通信：因为消息本身就可使入队的系统直接返回，所以说实现了程序的异步操作
场景扩展性：如 现在只有订单系统和财务系统，后续我想加个配货系统，直接让配货系统订阅这个队列就可以
排序保证：有些场景下，如 银行数据的处理顺序是很重要的，因为队列本身就可以做成单线程，单进单出的这种系统
实现介质：
1、使用mysql：可靠性高，易实现，速度慢
2、使用redis：速度快，单条大消息包时效率低
3、使用更专业的第三方类库：专业性强，可靠，学习成本高。
请参考我这篇博客http://blog.csdn.net/qq_33862644/article/details/79386484
消息处理触发机制：
1、死循环方式读取：易实现，故障时无法及时回复（适用于秒杀这种短时间的）
2、定时任务：压力均分，有处理上限（无论你队列前的系统，峰值多么不稳定，队列后的系统依然会定时执行）
注意：定时时间是个关键：不要上一个还定时任务没执行完，下一个定时任务就启动了
案例：订单系统，下单后将订单信息写入队列后，立刻返回下单成功。配货系统每隔几分钟定时读取队列，对订单进行汇总处理
3、守护进程：类似于php-fpm和cgi，需要shell基础（用这个进程来检测，队列中是否有内容，有内容的话，启动出队系统进行处理）
使用mysql实现解耦案例：
为什么要解耦：如果架构在一起。订单系统压力大，而物流信息是不需要立刻返回的。订单崩了，物流也就蹦了，所以要解耦

表的设计：

订单系统写入队列的代码：

配货系统读取队列的代码：

执行定时任务Crontab -e

注意：这日志文件要自己新建
1、通过浏览器访问order.php添加订单
2、去数据库看结果，在shell中的日志中看结果(没有执行成功，可能是这sh文件需要放在某个特点目录吧，等复习完 在跑)
使用redis进行流量削锋案例

思路：
1、秒杀程序请求写入redis
2、检查redis已存放数据的长度，超出上限直接丢弃（返回秒杀结束）
3、死循环处理存入redis的数据并入库
表的设计：

秒杀代码：

入库代码：

浏览器直接访问user.php
在shell中使用php -f savetodb.php
去数据库查看
转载自公众号


展开全文
• 学习阻塞队列之前需要掌握线程wait(),notify()以及notifyAll()相关知识! ①wait()为什么要放置在while循环中,而不是使用if进行判断 ②notify()和notifyAll()有什么区别?为什么有时候认为该使用notify()地方...
学习阻塞队列之前需要掌握线程的wait(),notify()以及notifyAll()的相关知识!

①wait()为什么要放置在while循环中,而不是使用if进行判断

②notify()和notifyAll()有什么区别?为什么有时候认为该使用notify()的地方却使用了notifyAll()?

上面这两个问题是我在学习多线程时产生的疑问,我相信也会是大多数人的疑问

下面是相关介绍:

JVM会为一个使用内部锁的对象维护两个集合EntrySet(锁池)和WaitSet(等待池)

①EntrySet:线程A持有对象锁,其它线程若想获得该对象锁,只能进入EntrySet,并且处于线程的BLOCKED状态
②WaitSet:线程A调用了wait()方法后会释放该对象的锁,进入WaitSet,并且处于线程的WAITING状态
线程B获得对象锁有两个条件:

①对象锁已经被释放(持有锁的线程A执行完了synchronized代码块,或者线程A调用了wait方法)
②线程B处于RUNNABLE状态
两个集合中的线程在什么条件下可以转变为RUNNABLE状态呢?

①EntrySet:当对象锁被释放后,JVM会唤醒EntrySet中某一线程,此线程的状态就由BLOCKED转为RUNNABLE
②WaitSet:
1>当对象的notify()方法被调用时,JVM会唤醒WaitSet中的某一线程,此线程状态由WAITING转为RUNNABLE
2>当对象的notifyAll()方法被调用时,WaitSet中的全部线程都被唤醒,这些线程状态由WAITING转为RUNNABLE
3>唤醒后的线程全部进入EntrySet中
当对象锁被释放后,所有处于RUNNABLE状态的线程会共同去竞争该对象锁,竞争失败的线程会在EntrySet中等待下一次机会

疑问解惑:

①wait()为什么要放置在while循环中,而不是使用if进行判断?

那生产者消费者为例,当前无可消费时,调用消费者的wait(),使其进入等待状态,但是消费者线程无法确定其它线程什么时候会被notify.多生产者多消费者的情况下这是无法预知并掌控的,极有可能发生的是唤醒生产者的是另一个生产者,唤醒消费者的是另一个消费者,如果将wait()放在if判断中就会造成过度生产过度消费的情况,典型如IndexOutOfBoundsException的异常。所以所有的java书籍都会建议开发者永远都要把wait()放到循环语句里面

②notify()和notifyAll()有什么区别?为什么有时候认为该使用notify()的地方却使用了notifyAll()?

我们应该尽量使用notifyAll()的原因就是，notify()非常容易导致死锁。当然notifyAll并不一定都是优点，毕竟一次性将Wait Set中的线程都唤醒是一笔不菲的开销，如果你能handle你的线程调度，那么使用notify()也是有好处的

阻塞队列与普通队列的区别:

①当队列为空时,从队列中获取元素的操作将被阻塞

②当队列为满时,向队列中添加元素的操作将被阻塞

一.阻塞队列的wait()和notify()方式实现

package blockqueue;

import java.util.List;

/**
* 第一种实现阻塞队列的方式是使用wait()和notify()
*/
public class BlockingQueueModeFir {
//使用list实现阻塞队列
private List queue = new LinkedList();
//有界队列上限
private int limit = 10;
//阻塞队列构造
public BlockingQueueModeFir(int limit) {
this.limit = limit;//指定队列上限
}

/**
* 向阻塞队列中添加元素
* @param item
* @throws InterruptedException
*/
public synchronized void enqueue(Object item) throws InterruptedException {
//阻塞队列中元素数已达上限,则执行添加元素的线程阻塞
while (this.queue.size() == this.limit){
wait();
}
//阻塞队列已被清空时,唤醒所有线程
if (this.queue.size() == 0){
notifyAll();
}
//阻塞队列存在元素且元素数量未达上限,向队列中添加元素
}

public synchronized Object dequeue() throws InterruptedException {
//当阻塞队列为空时,无法取出元素,执行等待
while (this.queue.size() == 0){
wait();
}
//当阻塞队列已满时,唤醒所有线程
if (this.queue.size() == this.limit){
notifyAll();
}
//阻塞队列存在元素且元素数量未达上限,取出队列中的元素
return this.queue.remove(0);
}
}


二.阻塞队列的并发式实现

package blockqueue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
* 第二种实现阻塞队列的方式是并发式
*/
public class BlockingQueueModeSec {
public static void main(String[] args) {
//缓冲区允许存放3个元素
final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(3);

//开启两个线程向队列中存入数据
for (int i = 0; i < 2; i++) {
while(true) {
try {
+ (queue.size() == 3?"..队列已满，正在等待":"..."));
queue.put(1);
+ "队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}

@Override
public void run() {
while(true) {
try {
+ (queue.size() == 0?"..队列已空，正在等待":"..."));
queue.take();
+ "队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
}).start();
}
}



展开全文
• BlockingQueue阻塞队列, 分为有界和无界队列, 常用有界队列即为ArrayBlockingQueue, 无界队列即为LinkedBlockingQueue, 虽然也有最大长达, 但最大长度为Integer.MAX_VALUE(21亿+). BlockingQueue接口中有以下方法 ...
• 链表结构决定了再链表头进行添加/删除操作时时间复杂度仅为O(1)...修改的方式就是添加一个尾指针,指向链表最后一个节点,这个操作只是针对实现队列优化,使得在链表尾部添加元素时间复杂度从O(n)将为O(1),也...
• 队列的概念：1、是队列结构的中间件2、消息放入后不需要立即处理3、由订阅者/消费者按顺序处理队列原理：也是解耦的原理：业务系统和队列处理系统没有关系一个写（业务系统），一...
• 之前消息队列的实现方式有很多种，比较常见的除了我们上文介绍的发布订阅模式，还有两种：List 和 ZSet 的实现方式。 List 和 ZSet 的方式解决了发布订阅模式不能持久化的问题，但这...
• c语言版队列实现，队列的实现是一种先进先出的策略。以下使用动态分配内存的数组和链表来实现一个队列。
• ## redis队列的实现

万次阅读 2017-05-23 20:09:30
关于redis队列的实现方式有两种： 1、生产者消费者模式。 2、发布者订阅者模式。   详解： 1、生产者消费者模式。 普通版本： 比如一个队列里面，生产者A push了一个数据进去，消费者B pop 了这个数据，那个这个...
• 假设front指向队列的头部，rear指向队列的尾部。 则队列满的条件是：(rear+1)%QueueSize==front 则队列为空的条件为：rear==...则队列的数组实现如下： private int[] array; private int front; private int rea...
• 细心的你可能发现了，竟然出现了三篇文章都是在说消息队列，程序级别的消息队列以及延迟消息队列的实现，讲了常见的消息队列中间件 RabbitMQ、Kafka 等，由此可见消息队列在整个 Java 技术体系中的重要程度。...
• 1、队列的描述 队列是一种先进先出的存储数据的结构。...3、队列的实现方式  3.1、队列与栈的实现方式一样，一般分为两种：线性队列与链式队列。  3.2、线性队列的描述  线性队列又可以分为普通队列...
• 很多情况下我们会收集一些元素，处理当前键值最大元素，然后再收集更多元素，再处理当前键值最大元素，如此... 一种基于堆得优先队列简单实现方式：  public class MaxPQ> { private Key[] pq; private int
• 优先队列一、优先队列的概念二、优先队列的API三、优先队列的初级实现（一）、数组实现（无序）（二）、数组实现（有序）（三）、链表表示法（四）、图表分析四、堆的定义（一）、堆的概念（二）、二叉堆表示法五、...
• 用数组方式实现队列，为了避免空间浪费，我们利用循环队列的方式，即当新成员入队时，如果队尾没有空间了，可以查询对头是否有空闲的空间，如果有，则入队，否则不入队。 入队时，只需rear+1，出队时，只需front+...
• 细心的你可能发现了，本系列课程中竟然出现了三个课时都是在说消息队列，第 10 课时讲了程序级别的消息队列以及延迟消息队列的实现，而第 15 课时讲了常见的消息队列中间件 RabbitMQ、Kafka 等，由此可见消息队列在...
• 队列简介： 队列是一种特殊的线性表，特殊之处在于...队列是一种最常用的数据结构，也是最重要的一种数据结构，这里介绍三种实现队列的方法： 1.基于链表来实现队列。 2.使用linkedList来实现队列。 3.使用两个...
• 队列这种结构，其实就跟现实中排队买票类似，先排队的，先买票。队列的特性就是先进先出。 队列的存储有顺序存储和链式存储之分，本文主要介绍如何用链表来实现队列。

...