In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
It is believed that many inexperienced people have no idea about how to carry out multithreaded programming applications in HTML5. Therefore, this paper summarizes the causes and solutions of the problems. Through this article, I hope you can solve this problem.
Brief introduction of worker Thread (Web Worker) in HTML5
Since the W3C drew up the first draft of HTML5 in 2008, HTML5 has carried more and more new features and functions. It not only strengthens the performance of Web systems or web pages, but also increases the support for Web application functions such as local database. Among them, the most important one is the support for multithreading. The concept of worker thread (Web Worker) is put forward in HTML5, and the three main characteristics of Web Worker are specified: the ability to run for a long time (response), ideal startup performance and ideal memory consumption. Web Worker allows developers to write daemons that can run for a long time without being interrupted by the user to execute transactions or logic while ensuring that the page responds to the user in a timely manner. This paper goes deep into the HTML5 multithreading specification, describes the principles and methods of multithreading implementation, and explains the multithreading programming and application in HTML5 in the form of an example.
The worker thread specification in W3C has so far defined a series of common interfaces that allow Web developers to create background threads to run scripts concurrently in their main page. This will make thread-level message communication a reality.
Detailed explanation of the principle of HTML5 worker thread
Traditionally, a thread can be interpreted as a lightweight process, which has independent execution control like a process, and is generally scheduled by the operating system. Multithreading in HTML5 is such a mechanism that allows multiple JavaScript scripts to be executed concurrently in Web programs. Each script execution flow is called a thread, which is independent of each other, and is managed by the JavaScript engine in the browser. Below we will explain the working thread principle of HTML5 in detail.
Worker thread and multithread programming
In HTML5, the advent of worker threads makes multithreaded programming possible in Web pages. As we all know, the JavaScript in traditional pages (before HTML5) works in a single-thread way. Although there are many ways to simulate multi-thread (for example, setinterval method in JavaScript, setTimeout method, etc.), in essence, the program is still run by the JavaScript engine in a single-thread scheduling way. The worker thread introduced in HTML5 enables the browser-side JavaScript engine to execute JavaScript code concurrently, thus realizing a good support for browser-side multithread programming.
Web Worker in HTML5 can be divided into two different thread types, one is dedicated thread Dedicated Worker, and the other is shared thread Shared Worker. The two types of threads have different uses. These two worker threads are described and described in detail below.
Dedicated thread: Dedicated Worker
1. How to create dedicated threads (dedicated worker):
When creating a dedicated thread, you need to provide the constructor of Worker with a URL that points to the JavaScript file resource, which is the only parameter required by the Worker constructor when creating a dedicated thread. When this constructor is called, an instance of the worker thread is created. The following is an example of creating dedicated thread code:
Listing 1. Create a dedicated thread sample code
Var worker = new Worker ('dedicated.js')
two。 Communicate with a dedicated thread:
Dedicated threads use MessagePort objects in the background while running, while MessagePort objects support all the functions provided by multiple threads in HTML5, such as sending and receiving structured data (JSON, etc.), transmitting binary data, and supporting data transfer in different ports.
In order to receive messages from the dedicated thread in the main program of the page, we need to use the worker thread's onmessage event handler. The example code that defines onmessage is as follows:
Listing 2. Receive sample code from worker threads
Worker.onmessage = function (event) {.}
3. In addition, developers can also choose to use the addEventListener method, which is ultimately implemented in the same way and works as onmessage.
As mentioned earlier, the dedicated thread uses an implicit MessagePort instance, and when the dedicated thread is created, the port message queue of the MessagePort is actively enabled. Therefore, this also works with the start method defined in the worker thread interface.
If we want a dedicated thread to send data, we need to use the postMessage method in the thread. Dedicated threads support not only the transfer of binary data, but also structured JavaScript data formats. It is important to note here that in order to transfer ArrayBuffer object data efficiently, you need to specify it in the second parameter in the postMessage method. The example code is as follows:
Listing 3. Efficient transmission of ArrayBuffer data codes
Worker.postMessage ({operation: 'list_all_users', / / ArrayBuffer object input: buffer, threshold: 0.8,}, [buffer])
Shared thread Shared Worker
1. Shared thread
Shared threads can be defined in two ways: one is created by pointing to the URL of the JavaScript script resource, but by an explicit name. When defined by an explicit name, the use of URL in the first page that creates the shared thread will be used as the JavaScript script resource URL for the shared thread. In such a way, it allows multiple applications in the same domain to use the same shared thread that provides common services, so that all applications do not need to keep in touch with the URL that provides common services.
In any case, the scope or effective scope of a shared thread is defined by the domain in which it was created. Therefore, there is no conflict between two different sites (that is, domains) using the same shared thread name.
two。 Creation of shared threads
Creating a shared thread can be done by using the SharedWorker () constructor, which uses URL as the first parameter, the URL pointing to the JavaScript resource file, and if the developer provides a second constructor, this parameter will be used as the name of the shared thread. An example of code to create a shared thread is as follows:
/ receive data from the port, including text data and structured data 1. Worker.port.onmessage = function (event) {define your logic here... }; / / send plain text data to the port
Worker.port.postMessage ('put your message here …'); / / send structured data to the port
Worker.port.postMessage ({username: 'usertext'; live_city: [' data-one', 'data-two',' data-three','data-four']})
3. Communicate with shared thread
The communication of shared threads is done through the use of implicit MessagePort object instances, just like dedicated threads. When the SharedWorker () constructor is used, the object is returned in a way that is referenced. We can communicate with this reference through its port port property. An example of the code to send and receive messages is as follows:
Listing 4. Send message and receive message code
In the above sample code, the first one uses the onmessage event handler to receive messages, the second uses postMessage to send plain text data, and the third uses postMessage to send structured data, here we use the JSON data format.
Worker thread event handling model
When a worker thread is created by a constructor with a URL parameter, it needs a series of processes to process and record its own data and state. Below, we give the following processing model for worker threads (Note: since the specification of worker threads in W3C is still being updated, when you read this article, you may see that it is no longer the latest processing model, it is recommended to refer to the latest specification in W3C):
1. Create a separate parallel processing environment and run the following steps asynchronously in this environment.
two。 If its global scope is a SharedWorkerGlobalScope object, associate the most appropriate application cache with it.
3. Try to get script resources from the URL it provides using the synchronous and force same-origin flags.
4. The following steps are followed when a new script is created:
Create the execution environment for this script.
Parse script resources using the execution environment of the script.
Set the global variable of the script to the worker thread global variable.
Sets the script encoding to UTF-8 encoding.
5. Start the thread monitor and close the orphan thread.
6. For suspended threads, start the thread monitor to monitor the status of suspended threads and immediately change their state in a parallel environment.
7. Jump to the starting point of the script and start the run.
8. If its global variable is a DedicatedWorkerGlobalScope object, then enable port message queuing in the implicit port of the thread.
9. For event loops, wait until a new task appears in the event loop list.
10. First run the first incoming task in the event loop list, but the user agent can choose to run any task.
11. If the event loop list has a stored mutex mutex semaphore, release it.
twelve。 When you have finished running a task, remove it from the event loop list.
13. If there are still tasks in the event loop list, continue with the previous steps to perform these tasks.
14. If the activity times out, clear the global scope list of the worker thread.
15. Release all ports in the worker's port list.
Application scope and scope of worker threads
The global scope of a worker thread is limited to the worker thread itself, that is, it is valid for the life cycle of the thread. The WorkerGlobalScope interface in the specification represents its global scope. Let's take a look at the implementation details of this interface (WorkerGlobalScope abstract interface).
Listing 5. WorkerGlobalScope abstract interface code
Interface WorkerGlobalScope {readonly attribute WorkerGlobalScope self; readonly attribute WorkerLocation location; void close (); attribute Function onerror;}; WorkerGlobalScope implements WorkerUtils; WorkerGlobalScope implements EventTarget
We can use the self property of WorkerGlobalScope or a reference to the object itself. The location property returns the WorkerLocation object associated with the thread when it is created, which represents the absolute URL used to initialize the footstep resource of the worker thread, and the location of the URL resource will not change even after the page has been redirected multiple times.
When the script calls the close () method on WorkerGlobalScope, it automatically performs the following two steps:
1. Delete all tasks in this worker thread event queue.
two。 Set the closing state of the WorkerGlobalScope object to true (this will prevent any new tasks from being added to the event queue later).
Worker thread life cycle
Communication between worker threads must depend on the browser's context and pass messages through their MessagePort object instances. The global scope of each worker thread has a list of ports for these threads, including the MessagePort objects used by all threads. In the case of dedicated threads, the list also contains implicit MessagePort objects.
The global scope object WorkerGlobalScope for each worker thread also has a list of threads for the worker thread, which is empty at initialization. When worker threads are created or have a parent worker thread, they are populated.
Finally, the global scope object WorkerGlobalScope for each worker thread also has the document model for that thread, and the list is empty at initialization. When the worker thread is created, the document object is populated. Whenever a document object is discarded, it is removed from the document object list.
In the lifecycle of worker threads, the following four different types of thread names are defined to identify their different states throughout the lifecycle of the thread:
When the document object enumeration of a worker thread is not empty, the worker thread is called a permission thread. (A worker is said to be a permissible worker if its list of the worker's Documents is not empty.)
A worker thread is called a protected thread when it is licensed and either has a database transaction or has a network connection or its list of worker threads is not empty. (A worker is said to be a protected worker if it is a permissible worker and either it has outstanding timers, database transactions, or network connections, or its list of the worker's ports is not empty)
When any object in the list of document objects of a worker thread is fully active, the worker thread is called the thread that needs to be activated. (A worker is said to be an active needed worker if any of the Document objects in the worker's Documents are fully active.)
When a worker thread is a non-activating thread and a licensed thread, the worker thread is called a suspended thread. (A worker is said to be a suspendable worker if it is not an active needed worker but it is a permissible worker.)
As the W3C Web Worker specification is still in the stage of perfection and has not formed the final specification, this paper also attaches the original definitions of the above four different states of the thread.
Worker thread (Web Worker) API interface
Access and introduction of class libraries and scripts
For the access and introduction of class libraries and scripts, the specification provides that the importScripts (urls) method of the WorkerGlobalScope object can be used to introduce script resources in the network. When the user calls this method to introduce the resource, the following steps are performed to complete the operation:
If you don't give any parameters to the importScripts method, return immediately, terminating the following steps.
Parse each parameter of the importScripts method.
If there are any failures or errors, throw a SYNTAX_ERR exception.
Try to get the script resource from the URL resource location provided by the user.
For each parameter of the importScripts method, get the script resources in the order provided by the user, and then proceed with other operations.
Listing 6. External resource scripts introduce and access sample code
/ * use the importScripts method to introduce an external resource script, where we use the mathematical formula calculation tool library math_utilities.js * when the JavaScript engine loads the resource file, continue to execute the following code. At the same time, the following code accesses and invokes the variables and methods defined in the resource file. * * / importScripts ('math_utilities.js'); / * * This worker is used to calculate * the least common multiple * and the greatest common divisor * / onmessage = function (event) {var first=event.data.first; var second=event.data.second; calculate (first,second);}; / * * calculate the least common multiple * and the greatest common divisor * / function calculate (first,second) {/ / do the calculation work var common_divisor=divisor (first,second) Var common_multiple=multiple (first,second); postMessage ("Work done!" + The least common multiple is "+ common_divisor +" and the greatest common divisor is "+ common_multiple);}
Working Navigator object (WorkerNavigator)
In HTML5, the navigator property of the WorkerUtils interface returns a working navigator object (WorkerNavigator) that defines and represents the identity and status of the user agent (that is, the Web client). Therefore, users and Web script developers can use this object to obtain or determine the user's status during multithreaded development.
Working Navigator object (WorkerNavigator)
The navigator property of the WorkerUtils abstract interface returns a WorkerNavigator user interface, which is used for the recognized status identification of the user agent. Let's look at the definition of the WorkerNavigator interface.
WorkerNavigator interface definition
Listing 7. WorkerNavigator interface definition code
Interface WorkerNavigator {}
WorkerNavigator implements NavigatorID
WorkerNavigator implements NavigatorOnLine
There is one thing to note: if the relative namespace object of the interface is a Window object, the WorkerNavigator object must not exist, that is, it can no longer be used.
Create and terminate threads
Before we talk about creating a new worker thread, let's take a look at the W3C specification's definition of a worker thread. The abstract interface class AbstractWorker of threads is defined in the worker thread specification, and both dedicated threads and shared threads inherit from this abstract interface. How to create dedicated threads and shared threads readers can refer to the sample code in the first section. The following is the definition of this abstract interface.
1.AbstractWorker Abstract Interface
Listing 8. AbstractWorker abstract interface code
In addition, the interface defines an event handler onerror for error handling, which is triggered when the worker thread encounters an error during communication.
two。 Dedicated thread and its definition
Listing 9. Dedicated thread definition code
[Constructor (in DOMString scriptURL)] interface Worker: AbstractWorker {void terminate (); void postMessage (in any message, in optional MessagePortArray ports); attribute Function onmessage;}
After creating a thread, we can call the terminate () method to terminate a thread. Each dedicated thread has an implicit MessagePort object associated with it. This port is created with the creation of the thread, but is not exposed to the user. All message receivers based on this port target the thread itself.
3. Shared thread and its definition
Listing 10. Shared thread definition code
[Constructor (DOMString scriptURL, optional DOMString name)] interface SharedWorker: AbstractWorker {readonly attribute MessagePort port;}
Shared threads are the same as dedicated threads. When a thread is created, we can call the terminate () method to terminate a shared thread.
Worker thread location attribute
After the worker thread is created, its status and location information need to be recorded, and WorkerLocation is defined in the worker thread specification to represent their location. The API is defined as follows:
Listing 11. Shared thread definition code
Interface WorkerLocation {/ / URL decomposition IDL attributes stringifier readonly attribute DOMString href; readonly attribute DOMString protocol; readonly attribute DOMString host; readonly attribute DOMString hostname; readonly attribute DOMString port; readonly attribute DOMString pathname; readonly attribute DOMString search; readonly attribute DOMString hash;}
The WorkerLocation object represents the absolute URL information of the worker thread script resource. We can use its href property to get the absolute URL of this object. The WorkerLocation interface also defines other attributes related to location information, such as: protocol for information transmission (protocol), host name (hostname), port (port), path name (pathname), and so on.
Application and practice of worker Thread (Web Worker)
We can write many examples to illustrate the appropriate use of background worker threads. Let's take several typical application scenarios as examples to explain the correct use of them in the context of various requirements in the form of code examples.
Application scenario 1: using worker threads for background numerical (algorithm) calculation
The simplest application of a worker thread is to do background computing, which does not interrupt the operation of the foreground user. Below we provide a code snippet of a worker thread to perform a relatively complex task: calculating the least common multiple and maximum common divisor of two very large numbers.
In this example, we create a background worker thread in the main page and assign a task to the worker thread (that is, passing two particularly large numbers). When the worker thread completes the task, the calculation result is returned to the main page program, and in the process, the main page does not need to wait for this time-consuming operation, and can continue to carry out other behaviors or tasks.
We divide this application scenario into two main parts, one is the main page, which can contain the main JavaScript application entry, other user operations UI, and so on. The other is a background worker thread script, which is used to perform computing tasks. The code snippet is as follows:
Listing 12. Main program page code
Background Worker Application Example 1: Complicated Number Computation The least common multiple and greatest common divisor is: please wait, computing...
Var worker = new Worker ('numberworker.js'); worker.postMessage ("{first:347734080,second:3423744400}"); worker.onmessage = function (event) {document.getElementById (' computation_result'). TextContent = event.data;}
Listing 13. Background worker thread code
/ * * This worker is used to calculate * the least common multiple * and the greatest common divisor * / onmessage = function (event) {var first=event.data.first; var second=event.data.second; calculate (first,second);}; / * * calculate the least common multiple * and the greatest common divisor * / function calculate (first,second) {/ / do the calculation work var common_divisor=divisor (first,second) Var common_multiple=multiple (first,second); postMessage ("Work done!" + "The least common multiple is" + common_divisor + "and the greatest common divisor is" + common_multiple);} / * * calculate the greatest common divisor * @ param number * @ param number * @ return * / function divisor (a, b) {if (a% b = = 0) {return b;} else {return divisor (b, a% b) }} / * calculate the least common multiple * @ param number * @ param number * @ return * / function multiple (a, b) {var multiple = 0; multiple = a * b / divisor (a, b); return multiple;}
In the main program page, we use the Worker () constructor to create a new worker thread that returns a thread object that represents the thread itself. Next we use this thread object to communicate with the background script. The thread object has two main event handlers: postMessage and onmessage. PostMessage is used to send messages to background scripts, and onmessage is used to receive messages passed from background scripts.
In the background worker thread code snippet, we specify two JavaScript functions, one is function divisor: to calculate the maximum common divisor and the other is function multiple: to calculate the least common multiple. At the same time, the worker thread's onmessage event handler is used to receive the values passed from the main page, and then pass these two values to function calculate for calculation. When the calculation is complete, the event handler postMessage is called to send the calculation result to the main page.
Application scenario 2: using shared threads to handle multi-user concurrent connections
Because the construction and destruction of threads consume a lot of system performance, such as CPU processor scheduling, memory occupation recovery and so on, there is the concept of thread pool in general programming languages. Thread pool is a form of concurrent processing of multi-threads. In the process of processing, the system adds all tasks to a task queue, and then automatically starts these tasks after the thread pool is built. After processing the task, the thread is returned to the thread pool for the next task call. Thread pool is also an application of shared threads.
Shared thread technology is also introduced in HTML5, but because each shared thread can have multiple connections, HTML5 provides a slightly different API interface to shared threads than normal worker threads. Here are a few examples of the use of shared threads.
Let's give an example: create a shared thread to receive instructions sent from different connections, then implement your own instruction processing logic, and return the results to different connected users after instruction processing.
Listing 14. Shared thread user connection page code
Shared worker example: how to use sharedworker in HTML5 var worker = new SharedWorker ('sharedworker.js'); var log = document.getElementById (' response_from_worker'); worker.port.addEventListener ('message', function (e) {/ / log the response data in web page log.textContent = e.data;}, false); worker.port.start (); worker.port.postMessage (' ping from user web page..') / / following method will send user input to sharedworker function postMessageToSharedWorker (input) {/ / define a json object to construct the request var instructions= {instruction:input.value}; worker.port.postMessage (instructions);} Shared worker example: how to use sharedworker in HTML5 send instructions to sharedworker:
Listing 15. Shared thread code for processing user instructions
/ / create a shared thread to receive instructions sent from different connections, and return the results to different connected users after instruction processing. / * * define a connect count to trace connecting * this variable will be shared within all connections * / var connect_number = 0; onconnect = function (e) {connect_numberconnect_numberconnect_number = connect_number+ 1; / / get the first port here var port = e.ports [0]; port.postMessage ('A new connection! The current connection number is'+ connect_number); port.onmessage = function (e) {/ / get instructions from requester var instruction=e.data.instruction; var results=execute_instruction (instruction); port.postMessage ('Request:' + instruction+' Response'+ results + 'from shared worker...');};}; / * * this function will be used to execute the instructions send from requester * @ param instruction * @ return * / function execute_instruction (instruction) {var result_value / / implement your logic here / / execute the instruction... Return result_value}
Listing 16. The main page (used only to display the calculation results) code
Shared worker example: how to use delegationworker in HTML5 var worker = new SharedWorker ('delegationworker.js'); var log = document.getElementById (' response_from_worker'); worker.onmessage = function (event) {/ / resolve the population from delegationworker var resultdata=event.data; var population=resultdata.total_population; var showtext='The total population of the word is'+ population; document.getElementById ('response_from_worker'). TextContent = showtext;} Shared worker example: how to use delegation worker in HTML5
Listing 17. Main worker thread code
/ * * define the country list in the whole word * take following Array as an example * / var country_list = ['Albania','Algeria','American','Andorra','Angola','Antigua','....']; / / define the variable to record the population of the word var total_population=0; var country_size=country_list.length; var processing_size=country_list.length; for (vari = 0; I < country_size) Subworker.js' +) {var worker = new Worker ('subworker.js'); / / wrap the command, send to delegations var command= {command:'start',country:country_ list [I]}; worker.postMessage (command); worker.onmessage = update_results;} / * * this function will be used to update the result * @ param event * @ return * / function storeResult (event) {total_population + = event.data; processing_size-= 1 If (processing_size
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.