Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript是如何实现单线程的?_Javascript_Multithreading - Fatal编程技术网

Javascript是如何实现单线程的?

Javascript是如何实现单线程的?,javascript,multithreading,Javascript,Multithreading,我对Javascript的单线程特性有一个疑问 console.log("1"); setTimeout(function(){console.log("2");},3000); console.log("3"); setTimeout(function(){console.log("4");},1000); 此代码的结果是1 3 4 2。正如您所看到的,4在2之后,这让我想知道在单线程环境中,2不应该在4之后吗?如果没有,那么JS怎么知道第二个setTimeout应该在第一个之前完成?是否应

我对Javascript的单线程特性有一个疑问

console.log("1");
setTimeout(function(){console.log("2");},3000);
console.log("3");
setTimeout(function(){console.log("4");},1000);
此代码的结果是
1 3 4 2
。正如您所看到的,
4
2
之后,这让我想知道在单线程环境中,
2
不应该在
4
之后吗?如果没有,那么JS怎么知道第二个
setTimeout
应该在第一个之前完成?是否应该有两个线程同时工作以完成两个
setTimeout
s以通知
EventLoop

JavaScript(在浏览器中)不会同时运行2

一次最多只能执行一个
setTimeout
回调,因为只有一个JavaScript执行上下文或“线程”

但是,要运行的“下一个计划超时”始终处于运行状态。。下一个“4”在“2”回调之前运行,因为它计划运行得更快。超时有效地安排在同一时间(没有任何操作被阻塞),但“2”的间隔要长得多

底层实现可能使用threads1,但同一全局上下文中的JavaScript不会并发运行,并保证所有回调之间的一致性和原子行为


1或者不可以;这可以在
select/poll
实现中不使用任何线程来处理


2在相同的上下文中:即选项卡/窗口、WebWorker、主机浏览器控件。例如,虽然WebWorker是并发运行的,但它们在不同的上下文中运行,并遵循相同的异步模型(例如计时器使用的异步模型)。

Javascript按顺序执行每一行

所以你告诉js:

  • 写入1:
    js写入1
  • 等3秒钟,然后写2:
    好的,我等3秒钟……现在怎么办?

  • 写3:
    好的,我写3,顺便说一下,3秒钟还没到。
  • 等待1秒钟,然后写入4:
    好的,我将等待1秒钟…
然后js等待.99999秒。。。写了4个


然后再等待一段时间并写入2

setTimeout的第二个参数将占用最短时间之后,回调函数(第一个参数)将被推送到事件循环上,事件循环只是回调函数的队列。此队列用于实际开始执行

一旦遇到第一个setTimeout,函数就会被推到外面的某个地方,并被告知在重新进入单线程世界之前等待3秒钟。第二个超时函数也会发生同样的情况,但它只需等待1秒。这个单线程世界的入口点是回调队列。JS引擎继续正常执行,就好像settimeout执行已完成一样。现在,一旦1秒过期,第二个超时功能就会被推到队列上,等待执行。如果此时调用堆栈已清除,则函数将进行处理(假定它是队列的第一个成员),并打印“4”。现在,如果这段时间还没有过3秒,第一个超时的功能仍然在外面某处等待。3秒钟过后,回调函数进入队列,由于调用堆栈已清除,它将执行并打印“2”

现在,浏览器可以从操作系统访问多个线程(尽管只为JS执行提供单线程环境)。这些设置超时由幕后的另一个线程处理

Philips Robert的视频完美地解释了导致单线程javascript“异步”的队列和事件循环的概念

console.log("1");
setTimeout(function(){console.log("2");},3000);
console.log("3");
setTimeout(function(){console.log("4");},1000);

Javascript使用名为Eventloop的东西进行异步调用。 setTimeout被推送到EventLoop,因为它是一个回调。并且主线程继续执行。一旦main完成,EventLoop就会将数据推送到主堆栈。 例:

当超时为0时,则代码的输出为

1234

因为它首先执行Main的调用,然后从Eventloop返回数据 以下是步骤:

  • 将console.log(1)添加到JS调用堆栈中。时间(~0)

  • 执行它。(在控制台中打印1)-时间(~0)

  • 添加setTimeout(function(){console.log(“2”);},3000);到调用堆栈。-时间(~0)

  • 将其移动到事件循环并启动计时器。-时间(3秒)

  • 由于setTimeout是一个异步函数,它将移动到事件循环

  • 将console.log(3)添加到JS调用堆栈中。时间(~0)

  • 执行它。(在控制台中打印3)时间(~0)

  • 添加setTimeout(function(){console.log(“4”);},1000);到调用堆栈。时间(~0)

  • 将其移动到事件循环并启动计时器。-时间(1秒)

  • 1秒计时器已完成,因此它将移回调用堆栈并执行

  • 调用堆栈执行它。(在控制台中打印4)-时间(~0)

  • 3秒计时器完成后,将移回调用堆栈并执行

  • 调用堆栈执行它。(在控制台中打印2)-时间(~0)

  • 现在我们调用的是同步的JS调用堆栈,它一次只能执行一件事情


    我本可以让它成为一个20步的过程,但为了便于理解,12步就足够了。

    定义-多线程: 多线程是一种执行模型,它允许多个线程在一个进程的上下文中存在,以便它们独立执行,但共享其进程资源。 从这个意义上讲,JavaScript完全是多线程的:

       let Ar;
        Ar = []
    
        function multiapp(ar,w,n) {
            ar.clear;
            for (let i = 0; i < n; i++)
                setTimeout(function(){ar.push(w)},i);
        }
    
        +function fn() {
            //Thread 1
            setTimeout(() => multiapp(Ar,1,10),100)
            //Thread 2
            setTimeout(() => multiapp(Ar,2,10),100)
        }()
    
        setTimeout(function(){console.log('Ar(1) = ', Ar.filter((i) => i == 1).length,'Ar(2) = ', Ar.filter((i) => i == 2).length,' Ar = ',Ar)},2000);
    //Ar(1) =  10 Ar(2) =  10  Ar =  [ 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 ]`
    
    let-Ar;
    Ar=[]
    功能多应用程序(ar、w、n){
    ar.clear;
    for(设i=0;imultiapp(Ar,1,10),100)
    //线程2
    setTimeout(()=>multiapp(Ar,2,10),100)
    }()
    setTimeout(函数(){控制台。