Потоки (Threads), Слушатели(Listeners) и События (Events)
Потоки(Threads), Слушатели (Listeners) и События (Events)

Потоки Java

Когда Java-программа запускается, возникает единственный работающий поток – основной поток (main thread).

Мнонгие из классов leJOS запускают дополнительные потоки для различных целей, например:

  • Классы Button и SensorPort запускают поток слушателя, если слушатели используются.
  • Класс NXTRegulatedMotor (и, следовательно, Motor) запускает поток-regulator
  • Класс Bluetooth запускает поток для "общения" с чипом Bluetooth
  • Каждый объект Timer-а запускает поток таймера
  • Некоторые из навигационных классов, например, NavPathController, запускают дополнительные потоки.

Программа пользователя может создать свои собственные потоки путём наследования класса Thread, и затем, используя метод start запустить поток. В leJOS NXJ 0.7 и более поздних, потоки могут быть созданы из любого класса, который реализует интерфейс Runnable.

Фоновые потоки (background threads), которые не нужно завершать для того, чтоб завершить программу пользвателя, должны быть помечены как демоны путём вызова setDaemon(true).

При использовании потоков, необходимо быть внимательным, чтоб не столкнуться с проблемами, связанными с многопоточностью (concurrency issues). Когда происходит обращение к данным со стороны нескольких потоков, необходимо использовать синхронизацию, чтоб гарантировать, что данные не прочитаются в тот момент, когда они находятся в некорректном состоянии.

leJOS NXJ поддерживает стандартные механизмы синхронизации Java: синхронизированные методы и ключевое слово "synchronized" использующее мониторные объекты (не уверен за точность перевода этого предложения, в оригинале оно выглядело так: leJOS NXJ supports the standard Java synchronization mechanisms: synchronized methods and synchronized statements using a monitor object).

Чтоб увидеть пример потока leJOS, посмотрите на поток Indicators в leJOS StartUpText menu. Он используется для того, чтоб показывать уровень заряда батареи актуальным. Он читает значение каждую секунду и показывает его, когда меню загружает файлы или осуществляет связь с 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) {
      }
    }
  }
}

Метод main запускает этот поток так:

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

Наверх страницы

Слушатели (Listeners) и События (Events)

leJOS реализует потоки слушателей которые слушают определённые события.

Потоки слушателей поддерживают:

  • Возможность "слушать" кнопки (ожидать событий, связанных с кнопками)
  • Возможность "слушать" порты для подключения сенсоров (ожидать события, связанные с сенсорами)

Button listeners используются чтоб обнаружить нажатие кнопки, что бы программа ни делала в это время.

Чтоб ожидать нажатия какой-то конкретной кнопки, вы должны зарегистрироваться как listener этой button.

Пример:

import lejos.nxt.Button;
import lejos.nxt.ButtonListener;
import lejos.nxt.LCD;

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();
  }
}

Наверх страницы


Hosted by uCoz