同步事件多路分解如何成为忙碌等待的解决方案?

时间:2016-06-17 06:28:23

标签: javascript node.js javascript-events

我试图了解同步事件多路分解如何成为繁忙等待的解决方案。

假设有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
             }
        }
    }

上面的伪代码忙着等待。

现在在同步事件多路分解或说反应器模式中,事件监听器在事件发生时响应事件。但是,事件监听器如何在不忙于等待的情况下做到这一点?

4 个答案:

答案 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时间来遍历大部分时间都不可用的资源,而对于反应堆模式,它只会遍历可用资源。