Home > Web Front-end > JS Tutorial > Can JavaScript be multi-threaded?

Can JavaScript be multi-threaded?

高洛峰
Release: 2016-11-26 10:16:57
Original
994 people have browsed it

JavaScript's setTimeout and setInterval are two methods that can easily deceive other people's feelings, because we often think that when called, it will be executed in a predetermined way. I think many people feel the same way, such as


[javascript]
setTimeout( function(){ alert('Hello!'); } , 0);
setInterval( callbackFunction , 100);
setTimeout( function(){ alert('Hello!'); } , 0);
setInterval( callbackFunction , 100);


I think that the greeting method in setTimeout will be executed immediately, because this is not said out of thin air, but the JavaScript API document clearly defines the meaning of the second parameter as the number of milliseconds after which the callback method will be executed. will be executed. If it is set to 0 milliseconds here, of course it will be executed immediately.
Similarly, I have no doubt that the callbackFunction method of setInterval will be executed immediately every 100 milliseconds!

But as JavaScript application development experience continues to increase and Rich, one day you found a weird piece of code and couldn't figure it out:


[javascript]
div.onclick = function(){
setTimeout( function(){document.getElementById('inputField') .focus();}, 0);
};
div.onclick = function(){
setTimeout( function(){document.getElementById('inputField').focus();}, 0);
};


Since it is executed after 0 milliseconds, why use setTimeout? At this moment, your firm belief has begun to waver.

Until the last day, you accidentally wrote a piece of bad code:


[javascript]
setTimeout ( function(){ while(true){} } , 100);
setTimeout( function(){ alert('Hello!'); } , 200);
setInterval( callbackFunction , 200);
setTimeout( function( ){ while(true){} } , 100);
setTimeout( function(){ alert('Hello!'); } , 200);
setInterval( callbackFunction , 200);

First line of code Entering an infinite loop, but soon you will find that the second and third lines are not what you expected, the alert greeting has not appeared, and there is no news from callbacKFunction!

At this time, you are completely confused. This situation is It is difficult to accept, because the process of changing long-established cognitions to accept new ideas is painful, but the facts are before our eyes, and the search for the truth of JavaScript will not stop because of pain. Let us expand the JavaScript thread and A journey of timer exploration!

Open the clouds and see the bright moon www.2cto.com

The main reason for all the above misunderstandings is: subconsciously believing that the JavaScript engine has multiple threads executing, and the JavaScript timer callback The function is executed asynchronously.

In fact, JavaScript uses a blinding method to deceive our eyes most of the time. The backlight here must clarify the fact:

The JavaScript engine runs in a single thread, no matter where the browser is There is only one and only one thread running the JavaScript program at all times.

It also makes sense to run the JavaScript engine with a single thread. The single thread does not have to worry about complex issues such as thread synchronization, and the problem is simplified.

So what is a single-threaded JavaScript engine? How does it cooperate with the browser kernel to process these timers and respond to browser events?
The following is a brief explanation based on the browser kernel processing method.

The browser kernel implementation allows multiple threads to execute asynchronously, and these threads cooperate with each other under the control of the kernel. Maintain synchronization. If the implementation of a certain browser kernel has at least three resident threads: JavaScript engine thread, interface rendering thread, browser event trigger thread, in addition to these, there are also some threads that terminate after execution, such as HTTP request thread. These asynchronous threads will generate different asynchronous events. The following diagram illustrates how the single-threaded JavaScript engine interacts and communicates with other threads. Although the implementation details of each browser kernel are different, the calling principles are similar. .

JavaScript’s setTimeout and setInterval are two methods that can easily deceive others’ feelings, because we often think that when called, it will be executed in the established way. I think many people feel the same way, for example

Can JavaScript be multi-threaded?

As can be seen from the picture, the JavaScript engine in the browser is event-driven. The events here can be regarded as various tasks assigned to it by the browser. These tasks can originate from the code block currently executed by the JavaScript engine. For example, calling setTimeout to add a task can also come from other threads in the browser kernel, such as interface element mouse click events, scheduled trigger time arrival notifications, asynchronous request status change notifications, etc. From a code perspective, task entities are various callback functions. , the JavaScript engine has been waiting for the arrival of tasks in the task queue. Due to the single-thread relationship, these tasks have to be queued and processed by the engine one after another.

The above figure t1-t2..tn represents different time points, and tn corresponds to the following The small square represents the task at that time point. Assume that it is time t1 and the engine is running in the task block code corresponding to t1. At this time point, let us describe the status of other threads in the browser kernel.

T1 time:

GUI rendering thread:

This thread is responsible for rendering the HTML elements of the browser interface. When the interface needs to be repainted (Repaint) or a reflow is caused by some operation, this thread will be executed. Although this article focuses on explaining the JavaScript timing mechanism, it is necessary at this time Let’s talk about the rendering thread, because this thread is mutually exclusive with the JavaScript engine thread. This is easy to understand, because JavaScript scripts can manipulate DOM elements. When modifying the properties of these elements and rendering the interface at the same time, the element data obtained before and after the rendering thread may be inconsistent.

While the JavaScript engine is running the script, the browser rendering thread is in a suspended state, which means it is "frozen".

So, update the interface, such as adding nodes, in the script , updates such as deleting a node or changing the appearance of a node will not be reflected immediately. These operations will be saved in a queue and will be rendered when the JavaScript engine is idle.

GUI event triggering thread:

JavaScript script The execution does not affect the triggering of html element events. During the t1 time period, the user first clicks a mouse button. The click is captured by the browser event trigger thread and forms a mouse click event. As can be seen from the figure, for the JavaScript engine thread , this event is asynchronously transmitted to the end of the task queue by other threads. Since the engine is processing the task at t1, this mouse click event is waiting to be processed.

Timing trigger thread:

Note that the browser model timing counter here is not It is counted by the JavaScript engine, because the JavaScript engine is single-threaded. If it is in a blocked thread state, it cannot count the time. It must rely on the outside to time and trigger the timing, so the timing events in the queue are also asynchronous events.

As can be seen from the picture, During this t1 time period, after the mouse click event is triggered, the previously set setTimeout timing has also arrived. At this time, for the JavaScript engine, the timing trigger thread generates an asynchronous timing event and puts it in the task queue. This event It is queued after the click event callback and is waiting for processing.
Similarly, it is still within the t1 period, and then a certain setInterval timer is also added. Because it is interval timing, it is triggered twice in a row during the t1 period. These two events are queued to the end of the queue to be processed. It can be seen that if the time period t1 is very long, much larger than the setInterval timing interval, then the timing trigger thread will continuously generate asynchronous timing events and put them at the end of the task queue. No matter whether they have been processed or not, once t1 and the tasks before the first scheduled event have been processed, the scheduled events in these arrangements will be executed one after another without interruption. This is because, for the JavaScript engine, in the processing queue Each task in is processed in the same way, but the order of processing is different. After

t1 has passed, that is to say, the currently processed task has been returned, the JavaScript engine will check the task queue and find that the current queue is not empty, so it will take out the bottom of t2 The corresponding task is executed, and so on at other times. From this point of view:

If the queue is not empty, the engine will take out a task from the head of the queue until the task is processed, that is, after returning, the engine will run the next task. Other tasks in the queue cannot be executed before returning.

I believe you now have a clear understanding of whether JavaScript can be multi-threaded, and also understand the JavaScript timer operating mechanism. Let’s analyze some cases:

Case 1: setTimeout and setInterval

[javascript]

setTimeout(function(){
  /* Code block... */
  setTimeout(arguments.callee, 10);
}, 10);

setInterval(function (){
  /* Code block... */
}, 10);
setTimeout(function(){
  /* Code block... */
  setTimeout(arguments.callee, 10);
}, 10 );

setInterval(function(){

/*Code block... */

}, 10);

The two pieces of code look the same when they are combined, but in fact they are not. In the callback function in the first paragraph The setTimeout is to set a new setTimeout timing after the JavaScript engine is executed. Assume that there is a time interval from the completion of the previous callback processing to the start of the next callback processing. Theoretically, the execution time interval between two setTimeout callbacks >= 10ms. The second paragraph is set from setInterval After timing, the timing trigger thread will continuously generate asynchronous timing events every ten seconds and put them at the end of the task queue. Theoretically, the execution time interval between two setInterval callbacks is

Case 2: Is the ajax asynchronous request true? Asynchronous?

Many classmates and friends are confused. Since JavaScript is said to run in a single thread, is XMLHttpRequest really asynchronous after connecting?

In fact, the request is indeed asynchronous, but this request is opened by the browser in a new thread. request (see the picture above), when the status of the request changes, if a callback has been set previously, the asynchronous thread will generate a status change event and put it in the processing queue of the JavaScript engine to wait for processing. When the task is processed, the JavaScript engine is always single The thread runs the callback function, specifically, it is the function set by single-thread running onreadystatechange.



Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template