Multi-threaded JavaScript

If you’re a JavaScript Junkie (like me), and you haven’t checked out Rhino yet, you don’t know what you’re missing! Rhino is an open source implementation of JavaScript written entirely in Java.

Here’s a great article from IBM’s alt.lang.jre series about installing Rhino and other basics. I highly recommend it.

There are literally tons of topics to cover concerning what you can do in JavaScript with Rhino on your classpath. Rhino allows you to bend the JavaScript rules in a lot of fascinating ways — most of which fall into two categories:

  1. Accessing Java language features missing in JavaScript (think interfaces, abstract classes, threads).
  2. Using any Java API from JavaScript (think Collections framework, java.net, java.io… or anything!).

I know… cool, huh? On top of that, Rhino allows you to compile your JavaScript code to Java .class files. Yes, you can compile JavaScript directly to Java bytecodes. Oh the pure filth of it!

First, let’s start with a fun language feature that Java has and that JavaScript lacks… Threads! That way we can give an example of both of the numbered list items above in the form of the java.lang.Runnable interface and the java.lang.Thread class.

There are two basic ways to create threads in Java… you can just subclass Thread which implements Runnable, or implement Runnable in a separate class and then create a thread instance by passing your Runnable instance to the thread’s constructor. Although the first technique would suffice for our simple example, we’ll go with the second technique here to show how to implement interfaces in JavaScript as well. I’m going to assume you are familiar with Java threads already… if not, there’s an excellent multithreading learning trail in the lovely Java Tutorial which is free online (I bought the Third edition of the book recently just cuz I love the Java Tutorial so much).

From here on out, I’ll assume that you have installed Rhino, and understand Java thread-creation basics. An easy way to execute an arbitrary .js file from Rhino is to get Rhino on your classpath, and then use Rhino’s shell tool:


java org.mozilla.javascript.tools.shell.Main /path/to/my.js

I’m on OS X, and have added the following line to my /etc/bashrc file for ultimate convenience:


alias js='java org.mozilla.javascript.tools.shell.Main'

So now I can just do this:


js /path/to/my.js

Importing Java Classes

Next, I create a file called threads.js… When writing JavaScript for Rhino, you can access any Java classes on your classpath, but you must either explicitly specify their fully qualified class name (including packages) or you can use the special Rhino importPackage and importClass functions. Unlike Java, this restriction applies to the java.lang package as well, due to namespace collisions between classes in java.lang and the JavaScript built-in classes like String and Math. So, I’ll just import the classes I will need by adding the following line to the top of my threads.js file:


importClass(java.lang.Thread,
            java.lang.Runnable,
            java.lang.System);

Now I can access any of these three Java classes or interfaces without having to qualify them with java.lang.

Interfaces in JavaScript

As I mentioned, Rhino allows you to implement Java interfaces in your JavaScript. You may be wondering… how can you do that when the JavaScript 1.5 that we know and love (to hate) doesn’t have an implements keyword? (Interesting side note… JavaScript 2.0 apparently had Interfaces in an early spec proposal, but they have been dropped.) Rhino allows you to implement an interface without the implements keyword in a number of ways… we’ll just look at one in particular. It’s a very terse, very syntactically sweet technique that looks almost like anonymous classes in Java:


var r = new Runnable() {
    run: function() {
        System.out.println('yo');
    }
};

Is this blowing your mind? We just wrote an anonymous class in JavaScript!!! The syntax can be a little confusing, but notice that the run method is just declared in the usual Python dictionary-like Object syntax that JavaScript always uses… like this { name: function() { doSomehting(); } }. Just with extra whitespace to make it more intuitive.

Note that neither in normal JavaScript, nor in JavaScript meant for the Rhino interpreter, may you do this:


// SYNTAX ERROR… WILL NOT RUN
var o = new MyClass() {
    f: function() {
        System.out.println(’yo’);
    }
};

This syntax does not work normally in JavaScript, and in Rhino it only works for Java interfaces, so don’t get too excited. You can’t just write an anonymous class in JavaScript whenever you feel like it. There are basically other ways to acheive this effect, though. Of course, you can still write anonymous functions in JavaScript.

Multi-threaded JavaScript

So now that I’ve implemented the Runnable interface, I can pass my instance to a Thread constructor and start the thread just like in Java:


var r = new Runnable() {
    run: function() {
        System.out.println('yo');
    }
};

new Thread(r).start();

Then we can have more fun… consider the following script:


importClass(java.lang.Thread,
            java.lang.Runnable,
            java.lang.System);

new Thread(new Runnable() {
    run: function() {
        for (var i = 0; i < 5; i++) {
            System.out.println('Hey Boi');
            Thread.yield();
        }
    }
}).start();

new Thread(new Runnable() {
    run: function() {
        for (var i = 0; i < 5; i++) {
            System.out.println('Sup Guhrl');
            Thread.yield();
        }
    }
}).start();

When I execute this script with Rhino, I see the following output in my shell:


Hey Boi
Sup Guhrl
Hey Boi
Sup Guhrl
Hey Boi
Sup Guhrl
Hey Boi
Sup Guhrl
Hey Boi
Sup Guhrl

Multi-threaded, object-oriented JavaScript. I just feel so dirty.


About this entry