Concurrency / Threading with Javascript & GWT

NOTE: Please click here for a flash/actionscript version of this technique.

Javascript does not support concurrency. All code must be executed within a single thread. This means that processor intensive tasks could cause a web page to stall very quickly. This forces us to rely on server side operations for any large calculations.

Fortunately it is possible to simulate threading using javascript. The example below demonstrates psuedo-threading using the google web toolkit. The sample increments an integer from zero to one hundred million, displaying the count on the screen as it increments. If this code was executed in a for loop the web page would quickly become unresponsive.


In order to mitigate this problem we can configure our javascript application to stop incrementing the integer whenever the page needs to process any other event handlers. This allows our application to catch it’s breath whenever necesary.

As a consequence our procedure needs to be configured in such a way that it can be paused and resumed when needed. This means our large calculations need to be broken down into smaller calculations.

Press the ‘Start’ button for a demo.

 

Source for the demo can be downloaded here. The java code is explained below.

The example assumes a basic knowledge of GWT, setting up a new GWT project and debugging/running an application. The GWT Home page details everything needed to get up and running with GWT.

For simplicity all of the code used in this example is executed from the Main Entry Point’s onModuleLoad() method.

public void onModuleLoad()
    {
        final Label label = new Label("0");

        final Button button = new Button();
        button.setText("Start");

        button.addClickHandler( new ClickHandler() {

            @Override
            public void onClick(ClickEvent event)
            {
                button.setEnabled(false);

                DeferredCommand.addCommand(new IncrementalCommand()
                {
                  private int index = 0;

                  protected static final int COUNT = 100000000;

                  public boolean execute()
                  {
                    label.setText( Integer.toString(index) );

                    return ++index < COUNT;
                  }
                });
            }
        } );

        RootPanel.get().add(button);
        RootPanel.get().add(label);
    }

        final Label label = new Label("0");

        final Button button = new Button();
        button.setText("Start");

First we create a label and a button widget. The button is used to start the count and the label is used to display the count as it increments.

      button.addClickHandler( new ClickHandler() {

            @Override
            public void onClick(ClickEvent event)
            {
                button.setEnabled(false);

                DeferredCommand.addCommand(new IncrementalCommand()
                {
                  private int index = 0;

                  protected static final int COUNT = 100000000;

                  public boolean execute()
                  {
                    label.setText( Integer.toString(index) );

                    return ++index < COUNT;
                  }
                });
            }
        } );

This code is executed when the ‘Start’ button is pressed. Using GWT’s DeferredCommand class we add an Incremental Command to the queue. The Incremental Command is executed only when all other activity has finished procesing, preventing our javascript application from becoming unresponsive. The IncrementalCommand interface includes a boolean method ‘execute’. This method is called by the Deferred Command manager continuously–whenever possible–until it returns false. In this case until our integer has been incremented to 100 000 000.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *