io多路复用,复用的是监听线程,通过一个线程监听所有的网络请求比如客户端连接、读写就绪等。复用的是线程,多路是指多个网络线路。
服务器套接字ServerSocket 对象调用accept来接收客户端连接,何时有新连接到来是通过系统调用如select来得到通知的。redis为每个客户端连接指定指令队列以及响应队列。
io多路复用也叫事件轮询,select 轮询为例,如果没有事件到来,就会阻塞,或者超时返回。
zset内部使用跳表数据结构,可以在logn时间内查询删除增加。思路:zset 若使用单链表,且需要排序,最快也需要nlogn,如何 使得链表也可以使用"二分查找"。那么便可以设计这样一种数据结构,结点可以从高层到底层遍历寻找,一次的遍历可以加快寻找速度。总体上是多层单链表结构,但是上层结点是下层节点的子集,从而达到加快查找的效果。
class Skiplist {
private static final int MAX_LEVEL = 64;
private int level = -1;
private Node dummy = new Node();
class Node{
int val = Integer.MAX_VALUE;
Node[] next = new Node[MAX_LEVEL];
}
public Skiplist() {
}
public boolean search(int target) {
Node node = dummy;
for(int i = level;i >=0;i--){
while(node.next[i] != null && node.next[i].val <= target){
if(node.next[i].val == target){
return true;
}
node = node.next[i];
}
}
return false;
}
public void add(int num) {
int newLevel = getRandomLevel(0.5);
Node addNode = new Node();
addNode.val = num;
Node node = dummy;
//addNode 加入level 之上的层
for(int i = newLevel; i > level;i--){
node.next[i] = addNode;
}
for(int i = level ;i >= 0;i--){
while(node.next[i] != null && node.next[i].val < num){
node = node.next[i];
}
if(i <= newLevel){
addNode.next[i] = node.next[i];
node.next[i] = addNode;
}
}
if(level < newLevel){
level = newLevel;
}
}
public boolean erase(int num) {
//删除的思想:首先找到该元素 然后按层删除
boolean isNeed = false;
Node node = dummy;
Node[] pres = new Node[MAX_LEVEL];
for(int i = level;i >=0 ;i--){
while(node.next[i] != null && node.next[i].val <= num){
if(node.next[i].val == num){
isNeed = true;
pres[i] = node;
break;
}else{
node = node.next[i];
}
}
}
for(int i = MAX_LEVEL-1;i >= 0;i--){
if(pres[i] != null){
//System.out.println("-----"+pres[i].val);
pres[i].next[i] = pres[i].next[i].next[i];
}
}
return isNeed;
}
public int getRandomLevel(double p){
int res = 1;
while(Math.random() <= p && res < MAX_LEVEL) res++;
//System.out.println(res);
return res;
}
}