Threads, Listeners and Events


Threads, Listeners and Events

Java Threads

When a Java program starts, there is a single thread running – the main thread.

Many of the leJOS classes start extra threads running for various purposes, for example:

  • Button and SensorPort start a listener thread if listeners are used
  • Each Motor has a regulator thread
  • The Bluetooth class starts a thread to talk to the separate Bluetooth chip
  • Each Timer object starts a timer thread

User programs can create their own threads by subclassing Thread, and then using the start method to start the thread. In leJOS NXJ 0.7, Threads can be created from any class that implements the Runnable interface.

Background threads that do not need to terminate in order for the user program to terminate, should be marked as daemon threads by calling setDaemon(true).

When using threads, care should be taken with concurrency issues. When data items are accessed by multiple threads, synchronization is necessary to ensure that data is not read when it is in an inconsistent state.

leJOS supports the standard Java synchronization mechanisms: synchronized methods and synchronized statements using a monitor object. There are some restrictions in the way leJOS handles concurrency and synchronization – see the leJOS NXJ README.html file.

As an example of a leJOS thread, consider the Indicators thread in the leJOS StartUpText menu. This is used to keep the display of the battery level up to date, by reading its value every second, and to indicate when the menu is uploading files or doing other communication from the PC:


import lejos.nxt.LCD;

class Indicators extends Thread {
  private boolean io = false;

  public void ioActive() {
    io = true;
  }

  public void run() {
    String[] ioProgress = { ".   ", " .  ", "  . " };
    int ioIndex = 0;
    boolean rewrite = false;
    while (true) {
      try {
        if (io) {
          StartUpText.g.drawString("     ", 76, 0);
          ioIndex = (ioIndex + 1) % ioProgress.length;
          StartUpText.g.drawString(ioProgress[ioIndex], 78, 0);
          io = false;
          rewrite = true;
        } else if (rewrite) {
          LCD.drawString("   ", 13, 0);
          // invert when power is off
          StartUpText.g.drawString(" BT", 82, 0, !StartUpText.btPowerOn);
          StartUpText.g.refresh();
          rewrite = false;
        }
        Thread.sleep(1000);
      } catch (InterruptedException ie) {
      }
    }
  }
}			

The main method starts this thread by:


  Indicators ind = new Indicators();
  ind.setDaemon(true);	
  ind.start();
  			

Back to top

Listeners and Events

leJOS implements a listener thread that listens for particular events.

The listener thread supports:

  • Button Listeners
  • Sensor Port Listeners

Button listeners are used to detect when a button is pressed, whatever your program is doing at the time.

To listen for a press of a specific button, you register as listener for that button.

Example:


import lejos.nxt.*;

public class ListenForButtons {
  public static void main(String[] args) throws Exception {
    Button.ENTER.addButtonListener(new ButtonListener() {
      public void buttonPressed(Button b) {
        LCD.drawString("ENTER pressed", 0, 0);
      }

      public void buttonReleased(Button b) {
        LCD.clear();
      }
    });

    Button.ESCAPE.waitForPressAndRelease();
  }
}
  			

Back to top