如何实现队列和双队列
数据结构中队列的核心思想和咱们排队买票看电影一样,要害是谁排在后面,谁就能够先买到票。入队(enqeue),顾名思义就是在队伍前面加了一个人排队。依照先入先出的规定,排在最后面的人买完票了当前,就会出队(dequeue)。
双队列(deque)
通常咱们排队的时候,都是遵循先进先出的规定,然而在有些非凡的状况下,也会有特例。在 JavaScript 中呢,同样有一个 unshift() 的办法能够用来做到插队,咱们在上面例子里把它叫做 dequeAdd。还有另外一种状况就是如果有的人在队尾等不及了,也有可能来到,这样的话咱们能够借用弹出栈的 pop() 来实现,咱们在上面例子里把它叫做 dequeRemove
class Queue {constructor () {this.queue = [];
}
enqueue(item) {return this.queue.push(item);
}
dequeue() {return this.queue.shift();
}
dequeAdd(item) {return this.queue.unshift(item);
}
dequeRemove(item) {return this.queue.pop(item);
}
peek() {return console.log(this.queue[0]);
}
}
通过队列看浏览器工作治理
过程(process)和线程(thread)
Chromium 用的是多过程的架构(multi-process architecture)。一个新的标签页就是新的浏览器过程。
在一个浏览器过程里,会有多个线程。
Chromium 中有两个外围线程,一个是主线程,另外一个是 IO 线程。因为浏览器是面向前端用户的,所以对于它的架构设计来说,最次要的指标是让主线程和 IO 线程能够疾速响应。为了达到这个目标,就要把阻塞 IO 或简单运算分给其它的线程去解决,线程间通信问题通过消息传递来解决。
能够说 Chromium 用的是一个高并发,但不算是高并行的架构。对于页面加载的脚本中要执行的工作,会采纳工作队列的形式通过事件循环给到 UI 主线程。如果问题是主线程能够解决的,就会解决,如果解决不了的,就会给到 IO 线程或非凡线程来解决,解决的后果会通过音讯通信的形式给到主线程。
线程池有一个共享的工作队列
在 Chromium 线程治理当中,并不提倡用锁的构造,而是提倡序列或虚构线程治理的概念。因为在 Google 看来,序列自身就带有线程安全性。
因为在虚构线程治理中,只有当一个工作执行完,下一个工作才有可能被调配到线程池中的另一个工作线程来执行,所以下一个工作必定是基于上一个工作的后果来执行的。工作的执行具备前后程序。
这里咱们能够打一个比如,比方咱们在项目管理中,会有一个需要池,这个需要池就是咱们的工作队列,而虚构线程治理就如同一个项目经理。
在 Chromium 中,通常当有多个线程(worker thread)能够拜访一个数据资源,然而同一时间只容许一个线程来拜访这些资源或数据的时候,会用到锁。在 Chromium 当中应用的是互斥锁(mutex)。
环形队列和线程间数据传递
环形队列是一种非凡的队列。一个环形队列是首尾相连的。它也叫做环形缓冲区(ring buffer),能够用于过程或线程之间的数据传递。
为什么环形队列适宜做 Node 数据流缓存?最外围的益处是当一个数据元素被用掉后,其余数据元素不须要挪动其存储地位。
对于一个环形队列来说,咱们个别须要两个指针,一个是头指针,一个是尾指针。头指针指向的是下一个要退出的数据,尾指针指向下一个要读取的数据。当数据被读取时,咱们就减少尾指针;当数据被写入的时候,咱们就减少头指针。
举个例子,假如咱们有一个 16 位的缓冲,第一步,咱们退出了 4 位数据,头指针就挪动到了 3。如果再加 3 个的话,头指针就挪动到了 6。如果这时,咱们读取了前 4 个,那么尾指针就会到 4。
那么在程序中这种环形队列如何实现呢?从实现的角度,个别会建设两个数组,一个是原数组用来定义环形队列的属性和办法,第二个是理论用来存放数据的环形队列数组。在原数组外面,次要寄存 3 个要害属性,别离是头指针、尾指针和环形队列长度。同时,蕴含几个外围办法:原数组中属性的获取和设置,以及环形队列数组中数据的读和写。通过这种形式,就能够实现一个环形队列了。
上面咱们能够来看看它在缓存数据流中的利用。这种环形队列通常会和“生产者,消费者”模式一起用,也通常会加一个互斥锁到环形队列的读、写办法里,用来实现互斥拜访。如下图所示,咱们能够看到有 4 个工作线程。2 个是生产者,2 个是消费者。生产者负责写入数据,消费者读取数据。通过加锁的形式,在同一时间,只有一个生产者能够写入,在读的时候,也只有一个消费者能够读取。
在数据流这种大量数据继续进入到列队中,再从队列中取出做缓存解决的状况下,应用环形队列就大大增加了生产者和消费者之间协同单干的效率。
数据流缓冲在很多利用中都有体现,除了过程治理外,在网络和文件系统中,都会用到数据流缓冲。在网络中,字节数据都是依照包的大小分成块儿来传输的;在文件系统中,数据块儿都是依据内核的缓冲大小分成块儿来解决的。所以无论是 HTTP 的数据申请和反馈,还是文件到目的地的传输,这些数据的传输都会用到环形队列缓冲。