7/17/2008

Let me talk about Concurrent.Thread, a library that allows JavaScript to use multiple threads, since this greatly eases the difficulty associated with asynchronous communication in the AJAX development mentioned above. This is a free-software library implemented in JavaScript, available under the Mozilla Public License / GNU General Public License. You can download the source code from the website.

Let’s download and use the source code right away. Suppose that you have saved the downloaded source code as a file named Concurrent.Thread.js. Before doing anything else, let’s run the program below, which has a very naïve implementation:

Executing this program should display numbers starting with 0 in order.Numbers appear one after another, which you can view by scrolling the page. Now, let’s look at the source code in more detail. It uses a simple infiniteloop as indicated by while ( 1 ). In ordinary cases, a JavaScript program like this continues to use the one and only thread, causing the browser to look frozen. Naturally, it does not allow you to scroll the screen. Then, why does the above program allow you to scroll? The key is Concurrent.Thread.create() located above while ( 1 ). This is a method provided by the library; it is for creating a new thread. On a new thread, the function passed as the argument is executed. Let me slightly rewrite the program as follows:

In this program we have a new function f(), which shows numbers repeatedly. This is defined at the top, and the create() method is called twice with f() as arguments. The second argument passed to the create() method is passed to f() without modification. Executing this program shows some small numbers starting with 0, which are followed by some large numbers starting with 100,000 and small numbers again that follow up the first series of small numbers. Like this, you can observe that the program shows alternating lines of small numbers and large numbers. This indicates that two threads are running concurrently.

Let me show you another use of Concurrent.Thread. In the above example, the create() method was called to create a thread. It is also possible to create a thread without calling any library APIs at all. For example, the former example can be expressed as:

Inside the script tag, an infinite loop is written simply in JavaScript. You should take note of the type attribute of the tag: an unfamiliar value (text/x-script.multithreaded-js)is assigned to it. If this attribute is assigned to the script tag, then Concurrent.Thread executes the content of the tag on a new thread. You should remember that, in this case as well, the library body of Concurrent.Thread must be included.

With Concurrent.Thread, it is possible to switch execution context from one thread to another as needed even if you write a long and continuous program. Let me briefly talk about how this behavior is achieved. In short, code conversion is used. Very roughly speaking, the function passed to the create() method is first converted to a character string, which is then rewritten so that it can be executed on a piecemeal basis. Then, the rewritten function is executed little by little on the scheduler. The scheduler is responsible for coordinating multiple threads. In other words, it makes adjustments so that each of the rewritten functionswill be evenly executed. Concurrent.Thread actually does not create new threads but simply simulates a multi-threaded environment on the original single thread.

Although the converted functions appear to be running on different threads, there is actually only one thread running everything. Carrying out synchronous communication within the converted functions will still cause the browser to freeze. You may think that our original problem has not been solved at all, however you don’t have to worry. Concurrent.Threadprovides a purpose-built communications library which is implemented using the asynchronous JavaScript communication style and which is designed to allow the other threads to work even when a thread is waiting for a response from the server. This communications library is found under the Concurrent.Thread.Http namespace. For example, it is used as follows:

The get() method retrieves the content of thespecified URL using HTTP GET,as its name suggests. It takes a target URL as the first argument and an arrayrepresenting HTTP header fields as the optional second argument. The get() method communicates with the serverand returns an XMLHttpRequest object as the returnvalue when it has received the server response. When the get() method returns, the response had been received. It isnot necessary to use a callback function to receive the result. Naturally,there is no worry that the browser freezes while the program is waiting aresponse from the server. In addition, the post() method can be used to send data to theserver:

<script type="text/javascript" src="Concurrent.Thread.js"></script>

<script type="text/x-script.multithreaded-js">

varreq = Concurrent.Thread.Http.post(url, "key1=val1&key2=val2");

alert(req.statusText);

</script>

The post() method takes a destination URL as the first argumentand content body to be sent as the second argument. As with the get() method, you can also assign header fields by theoptional third argument.

If you implement getArticle() in the first example using thiscommunications library, then you can quickly write getArticleWithCache(), backgroundLoad(), and other functions that use getArticle() using the naïve method shown at thebeginning of this article. Even when that version of backgroundLoad() is reading article data, anotherthread can respond to users as a matter of course, and the browser thereforedoes not freeze. Now, do you understand how useful it is to use multiplethreads in JavaScript?