我试图了解同步事件多路分解如何成为繁忙等待的解决方案。
假设有3个IO操作,并且我们有一个不断循环的代码,以检查3个操作中是否有任何数据可供读取。
arry = [event1 , event2 , event3]
while(arry is not empty)
{
for(i = 0 ; i <= 2 ; i++)
{
if(arry[i] has something to read)
{
read data;
}
else
{
continue to next i;
}
if(arry[i] read has finished){
remove i from arry
}
}
}
上面的伪代码忙着等待。
现在在同步事件多路分解或说反应器模式中,事件监听器在事件发生时响应事件。但是,事件监听器如何在不忙于等待的情况下做到这一点?
答案 0 :(得分:0)
这不是JS的工作方式。
当您提出某些可能触发异步通知的请求时,您必须提供一个回调,该回调将使用请求结果作为参数进行调用。
您的伪代码看起来像:
// request completion callback
function handle_request_notification (request status and associated data)
{
store request data wherever you like
if all requests are complete (without error), do what you want to do
(now that you have a complete set of data)
}
// issuing requests
do_request (whatever1, handle_request_notification)
do_request (whatever2, handle_request_notification)
do_request (whatever3, handle_request_notification)
所以基本上它是处理异步请求的库,这些异步请求会在实际需要读取(或请求失败)时激活所需的代码位。
每个特定的库都有自己的方法。
你可以看看Ajax的开始,这可能是所有JS异步库的母亲。
或者,如果您想要更简单的东西来学习基础知识,只需使用计时器:)
答案 1 :(得分:0)
繁忙的等待浪费了CPU时间来检查大部分时间都不可用的资源。另一方面,事件多路分解器会在事件上进行迭代,因此仅在准备好要处理的数据时才进行迭代。
答案 2 :(得分:0)
进程是已执行的计算机程序的实例(执行任务或模块)。在一个进程中,我们可以有多个称为线程的组件。您可以可视化一个类似于待办事项列表的线程,该线程具有一些需要由计算机的CPU执行的指令。将线程视为工作者。
假设您有一个10层的公寓。而且,您只有一名工人进行指示,因此必须敲开每扇门才能从中收集数据。在繁忙的等待中,这位可怜的工人从一楼开始,将敲开每扇门以检查是否准备好接收数据。它将一直执行到顶层。然后,它将按照自己的方式执行相同的过程。这次它将跳过之前已经接收到数据的门。因此它将一直上下运行,直到从每个门接收数据为止。这基本上就是忙等待。
如您所见,使用单线程,我们可以无阻塞地处理不同的资源。但是,这样做效率不高,它将使CPU占用大量内存,并导致上下文切换,这对于CPU来说是额外的工作。另外,线程在等待时仍会浪费大部分时间,而CPU仍在工作。
为什么事件多路分解是一种解决方案或更有效?
除了所有这些繁重的工作,我们的单线程将不会运行。它不再是工作人员,现在是管理员,并且使用C ++的libuv库获得了额外的支持。 Libuv将使用事件多路分解器收集所有数据,多路分解器将包括来自哪个门的数据以及如何处理该数据,然后它将必要的数据传递到事件队列,然后事件队列将控件传递到事件循环。现在,事件循环的工作只是检查是否有等待事件,如果有,它将把它压入执行函数的调用堆栈。
事件多路分解器之所以称为同步,是因为它不会同时敲2个门。
真的很难用简单的方式来解释这个复杂的主题。希望对您有所帮助。
答案 3 :(得分:-1)
在上面的代码中,for循环将反复循环,这将浪费CPU资源。
另一方面,反应堆模式代码如下:
array = [event1 , event2 , event3];
while(events = demultiplexer.watch(array)) {
events.forEach(event => {
\\ Data must be available at this point
process(event.data);
array.remove(event);
})
}
此调用events = demultiplexer.watch(array)
是同步的,因此它将阻塞线程,直到任何资源可用为止。当其中一种资源可用时,多路分解器将返回它,然后才执行for循环。
因此,简而言之,繁忙的等待将浪费CPU时间来遍历大部分时间都不可用的资源,而对于反应堆模式,它只会遍历可用资源。