扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
整套实现:
创新互联公司-专业网站定制、快速模板网站建设、高性价比乌兰察布网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式乌兰察布网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖乌兰察布地区。费用合理售后完善,十载实体公司更值得信赖。
class Element{
int id;
String name;
Element(int a,String n){
id=a;name=n;
}
}
class SeqQueue{
int first,last,maxsize;
Element queue[];
SeqQueue(int i){
maxsize=i;
first=last=-1;
queue=new Element[i];
}
public void clear(){//置空
first=last=-1;
}
public boolean isEmpty(){//判空
if(first==-1)return true;
else return false;
}
public Element getFirst(){//取队列头元素
if(first==-1)return null;
else return queue[first+1];
}
public boolean isFull(){//判满
if((last+1)%maxsize==first)return true;
else return false;
}
public boolean enQueue(Element e){//入队
if(this.isFull())return false;
if(this.isEmpty())
first=last=0;
else
last=(last+1)%maxsize;
queue[last]=e;
return true;
}
public Element deQueue(){//出队
Element t=queue[first];
if(this.isEmpty())return null;
if(first==last){
queue[first]=null;
this.clear();
return t;
}
queue[first]=null;
first=(first+1)%maxsize;
return t;
}
public int getLength(){//队列长度
if(last=first)return last-first+1;
else return maxsize-(first-last)+1;
}
public void display(){//打印所有元素
int i,j;
for (i=first,j=0;jthis.getLength();i=(i+1)%maxsize,j++)
System.out.println(queue[i].id);
}
}
数据的情况:
[0] [1] [2] [3] [4]
加入一个:
[0] [1] [2] [3] [4] [5]
取出一个后
[0] [1] [2] [3] [4] [5]
可以看出来,每次取出第一个,第一个元素还是没变,一直是0
要让其数据变成 [1] [2] [3] [4] [5] 那么就要自己手动变动数据(就是手动往前移动)
你这个只是进队 如果队列满了 只是会打印溢出,并不会对数组integerQueue有任何的影响,所以当 1 2 3 4 5的时候,进来的6并不会加入队列里面。如果出队列你改变的并不是数组,而只是tail,
所以当 队列是 1 2 3 4 5 的时候,出队列了,只是让tail改成3,但是整个数组的长度还是5,所以打印数组的时候还是 1 2 3 4 5
你可以在打印的时候 for(int i=0;iintegerQueue.length;i++)改for(inti=0;i=tail;i++);
分析:
redis的list底层是多个ziplist结构组成的“双向”链表。中间部分还压缩了一下。
最外层是由两个哈希表构成的dict。
哈希表的get(key)时间复杂度为O(1),而且这个O(1)理论上不会因为所占内存的大小和元素数目所改变。list的出队列和入队操作也都是O(1)。
Java的队列时间复杂度也应为O(1)。
可不可以直接用redis的list做先进先出?
情况1,数据数量不多,可以用
情况2,数据量多,但存的数据是激活码这样简单值一类,可以用。
情况3,list存的是要获取数据的索引,大量数据的值已经存在redis的KV结构中。
这时候,如果数据每次获取下一个数据都要执行redis的hash查找(O(1))然后redis的list从头或者末尾出一个。经过网络IO返回,Java程序在用出来的key去请求redis去get(key) (O(1))。这里是两次网络IO或者进程间的IO。
这时候,可以不用redis的list存索引而只是用redis大的KV哈希结构存键值。用①Java的队列先进先出获取下一个key或者②使用预先规定好的键生成的规则,让键是有规则有顺序的,比如自增ID,然后每次获取都是ID++,而直接从redis.get(ID.next());来获取值。
最后一种就是最高效的办法,为了特殊场景的高效出队列而设计。但是如果只是一般的数据量,使用redis的list也未尝不可。
import java.util.ArrayList;
/**
*
* @author 狱韬
*/
public class SnakeBody {
private int size=0; //队列的长度
private int cursor=-1; //指针
private ArrayListint[] list=null; //存储器
public SnakeBody() {
list=new ArrayListint[](); //存储器
}
//返回底部的数据
public int[] getLast(){
return list.get(list.size()-1);
}
//返回顶部的数据
public int[] getFirst(){
return list.get(0);
}
//压入数据
public void put(int[] arry){
list.add(arry);
}
//删除底部数据
public void removeLast(){
list.remove(list.size()-1);
}
//重置
public void reSet(){
list=new ArrayListint[](); //存储器
}
//删除顶部数据
public void removeFirst(){
list.remove(0);
}
//返回数据长度
public int size(){
return list.size();
}
public static void main(String[] args) {
SnakeBody data = new SnakeBody();
for(int i=0;i10;i++){
data.put(new int[]{0,i});
}
System.out.println(data.getFirst()[0]+"-------"+data.getFirst()[1]);
System.out.println(data.getLast()[0]+"-------"+data.getLast()[1]);
data.removeLast();
System.out.println(data.getFirst()[0]+"-------"+data.getFirst()[1]);
System.out.println(data.getLast()[0]+"-------"+data.getLast()[1]);
}
}
消息队列,顾名思义 首先是个队列。
队列的操作有入队和出队
也就是有一个程序在产生内容然后入队(生产者)
另一个程序读取内容,内容出队(消费者)
这是最最基本的概念。
java中的消息队列
消息队列是线程间通讯的手段:
import java.util.*
public class MsgQueue{
private Vector queue = null;
public MsgQueue(){
queue = new Vector();
}
public synchronized void send(Object o)
{
queue.addElement(o);
}
public synchronized Object recv()
{
if(queue.size()==0)
return null;
Object o = queue.firstElement();
queue.removeElementAt(0);//or queue[0] = null can also work
return o;
}
}
因为java中是locked by object的所以添加synchronized 就可以用于线程同步锁定对象
可以作为多线程处理多任务的存放task的队列。他的client包括封装好的task类以及thread类
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流