3D 打印传感器,塑料瓶能联网,拧瓶盖即可提供动力
图片来源于网络,侵删 总结一下就是上面列表的四个小标题,为了减少获取字符串长度开销、避免缓冲区溢出、空间预分配&空间惰性释放和保证二进制安全。 3. List List也是一个使用频率很高的数据结构,其涉及到的命令太多了,就不像String那样一个一个演示了,感兴趣的大家可以去搜一搜。命令有lpush、lpushx、rpush、rpushx、lpop、rpop、lindex、linsert、lrange、llen、lrem、lset、ltrim、rpoplpush、brpoplpush、blpop、brpop,其都是对数组中的元素的操作。 3.1 使用 List的用途我认为主要集中在以下两个方面。 当作普通列表存储数据(类似于Java的ArrayList) 用做异步队列 普通列表这个自然不必多说,其中存放的必然业务中需要的数据,下面来着重聊一下异步队列。 啥玩意,List还能当成队列来玩? List除了能被用做队列,还能当作栈来使用。在上面介绍了很多操作List命令,当我们用rpush/lpop组合命令的时候,实际上就是在使用一个队列,而当我们用rpush/rpop命令组合的时候,就是在使用一个栈。lpush/rpop和lpush/lpop是同理的。 假设我们用的是rpush来生产消息,当我们的程序需要消费消息的时候,就使用lpop从异步队列中消费消息。但是如果采用这种方式,当队列为空时,你可能需要不停的去询问队列中是否有数据,这样会造成机器的CPU资源的浪费。 所以你可以采取让当前线程Sleep一段时间,这样的确可以节省一部分CPU资源。但是你可能就需要去考虑Sleep的时间,间隔太短,CPU上下文切换可能也是一笔不小的开销,间隔太长,那么可能造成这条消息被延迟消费(不过都用异步队列了,应该可以忽略这个问题)。 除了Sleep,还有没有其他的方式? 有,答案是blpop。当我们使用blpop去消费时,如果当前队列是空的,那么此时线程会阻塞住,直到下面两种condition。
比起Sleep一段时间,实时性会好一点;比起轮询,对CPU资源更加友好。 3.2 原理 在Redis3.2之前,Redis采用的是ZipList(压缩列表)或者LinkedList(链表)。当List中的元素同时满足每个元素的小于64字节和List元素个数小于512个时,存储的方式为ZipList。但凡有一个条件没满足就会转换为LinkedList。 而在3.2之后,其实现变成了QuickList(快速列表)。LinkedList由于是较为基础的东西,此处就不赘述了。 3.2.1 ZipList ZipList采用连续的内存紧凑存储,不像链表那样需要有额外的空间来存储前驱节点和后续节点的指针。按照其存储的区域划分,大致可以分为三个部分,每个部分也有自己的划分,其详细的结构如下。
如果采用链表的存储方式,链表中的元素由指针相连,这样的方式可能会造成一定的内存碎片。而指针也会占用额外的存储空间。而ZipList不会存在这些情况,ZipList占用的是一段连续的内存空间。 但是相应地,ZipList的修改操作效率较为低下,插入和删除的操作会设计到频繁的内存空间申请和释放(有点类似于ArrayList重新扩容),且查询效率同样会受影响,本质上ZipList查询元素就是遍历链表。 3.2.2 QuickList
在3.2版本之后,list的实现就换成了QuickList。QuickList将list分成了多个节点,每一个节点采用ZipList存储数据。 (编辑:莆田站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |