Главная » Java » Использование Runnable

0

В интерфейсе Runnable абстрагируется концепция некой сущности, выполняющей программу во время своей активности. Интерфейс Runnable объявляет всего один метод:

public void run();

Класс Thread реализует интерфейс Runnable, поскольку поток как раз и является такой сущностью — во время его активности выполняется программа. Мы уже видели, что для осуществления каких-то особых вычислений можно расширить класс Thread, однако во многих случаях это не слишком просто. Прежде всего, расширение классов производится на основе одиночного наследования — если некоторый класс расширяется для того, чтобы он мог выполняться в потоке, то одновременно расширить и его, и Thread не удастся. Кроме того, если вам нужна только возможность выполнения, то вряд ли вы захотите наследовать и все накладные расходы, связанные с Thread.

Во многих случаях проще реализовать Runnable. Объект Runnable может выполняться в отдельном потоке — для этого следует передать его конструктору Thread. Если объект Thread конструируется с объектом Runnable, то реализация Thread.run вызывает метод run переданного объекта.

Приведем версию класса PingPong, в которой используется интерфейс Runnable. Сравнение этих двух версий показывает, что они выглядят почти одинаково. Наиболее существенные отличия заключаются в супертипе (Runnable вместо Thread) и методе main:

class RunPingPong inplements Runnable {

String word;               // выводимое слово

int delay;                 // длительность паузы

PingPong(String whatToSay, int delayTime) {

word = whatToSay;

delay = delayTime;

}

public void run() {

try {

for (;;) {

System.out.print(word + " "); Thread.sleep(delay); // подождать следующего

// вывода

}

} catch (InterruptedException e) {

return;                     // завершить поток

}

}

public static void main(String[] args) {

Runnable ping = new RunPingPong("ping",  33); Runnable pong = new RunPingPong("PONG", 100);

}

}

Сначала определяется новый класс, реализующий интерфейс Runnable. Код метода run в этом классе совпадает с его реализацией в классе PingPong. В методе main создаются два объекта RunPingPong с разными временными интервалами; затем для каждого из них создается и немедленно запускается новый объект Thread.

Существует четыре конструктора Thread, которым передаются объекты Runnable:

public Thread(Runnable  target)

Конструирует новый объект Thread, использующий метод run указанного класса target. public Thread(Runnable  target, String name)

Конструирует новый объект Thread с заданным именем name, использующий метод run

указанного класса target.

public Thread(ThreadGroup group, Runnable target)

Конструирует новый объект Thread, входящий в заданную группу ThreadGroup и использующий метод run указанного класса target.

public Thread(ThreadGroup  group, Runnable target, String name)

Конструирует новый объект Thread с заданным именем name, входящий в заданную группу ThreadGroup и использующий метод run указанного класса target.

9.12. Ключевое слово volatile

Механизм синхронизации помогает в решении многих проблем, однако, если вы откажетесь от его использования, сразу несколько потоков смогут одновременно изменять значение некоторого поля. Если это делается намеренно (может быть, для синхронизации доступа используются другие средства), следует объявить поле с ключевым словом volatile. Например, если у вас имеется переменная, значение которой постоянно отображается потоком графического вывода и может изменяться несинхронизированными методами, то фрагмент вывода может выглядеть следующим образом:

currentValue = 5;

for (;;) { display.showValue(currentValue); Thread.sleep(1000); // подождать 1 секунду

}

Если бы значение currentValue не могло изменяться внутри метода ShowValue, то компилятор мог бы предположить, что величина current Value остается в цикле постоянной, и просто использовать константу 5 вместо вызова showValue.

Однако, если во время выполнения цикла значение currentValue может быть изменено другим потоком, то предположение компилятора будет неверным. Объявление поля currentValue с ключевым словом volatile не позволяет компилятору делать подобные предположения.

Источник: Арнольд К., Гослинг Д. – Язык программирования Java (1997)

По теме:

  • Комментарии