Реализация интерфейса runnable Java

Реализация интерфейса runnable JavaСамый простой способ создать поток исполнения состоит в том, чтобы объ­явить класс, реализующий интерфейс Runnable. Этот интерфейс предоставляет абстракцию единицы исполняемого кода.

Поток исполнения можно создать из объекта любого класса, реализующего интерфейс Runnable. Для реализации ин­терфейса Runnable в классе должен быть объявлен единственный метод run():

В теле метода run() определяется код, который , собственно, и составляет но­вый поток исполнения. Однако в методе run() можно вызывать другие методы, ис­пользовать другие классы, объявлять переменные таким же образом, как и в главном
потоке исполнения.

Единственное отличие заключается в том, что в методе run() устанавливается точка входа в другой, параллельный поток исполнения в програм­ме. Этот поток исполнения завершится, когда метод run() возвратит управление.

После создания класса, реализующего интерфейс Runnable, в этом классе следует получить экземпляр объекта типа Thread. Для этой цели в классе Thread определен ряд конструкторов.

Тот конструктор, который должен использоваться в данном случае, выглядит в общей форме следующим образом:

В этом конструкторе параметр объект_потока обозначает экземпляр класса, реализующего интерфейс Runnable. Этим определяется место, где начинается вы­полнение потока.

Имя нового потока исполнения передается данному конструкто­ру в качестве параметра имя_потока.

После того как новый поток исполнения будет создан, он не запускается до тех пор, пока не будет вызван метод start(), объявленный в классе Thread. По суще­ству, в методе start() вызывается метод run().

Ниже показано, каким образом объявляется метод start().

Рассмотрим следующий пример программы, демонстрирующий создание и пуск нового потока на выполнение:

Новый объект класса Thread создается в следующем операторе из конструкто­ра NewThread():

Передача ссылки this на текущий объект в первом аргументе данного конструк­тора означает следующее: в новом потоке исполнения для текущего объекта по ссылке this следует вызвать метод run(). Далее в приведенном выше примере програм­мы вызывается метод start(), в результате чего поток исполнения запускается, начиная с метода run().

Это, в свою очередь, приводит к началу цикла for в дочер­нем потоке исполнения. После вызова метода start() конструктор NewThread() возвращает управление методу main().

Возобновляя свое исполнение, главный по­ток входит в свой цикл for. Далее потоки выполняются параллельно, совместно ис­пользуя ресурсы процессора в одноядерной системе, вплоть до завершения своих циклов.

Ниже приведен результат, выводимый данной программой (заметьте, у вас он может оказаться иным в зависимости от конкретной исполняющей среды).

Как упоминалось ранее, в многопоточной программе главный поток исполне­ния зачастую должен завершаться последним. На самом же деле, если главный по­ток исполнения завершается раньше дочерних потоков, то исполняющая система Java может «зависнуть», что характерно для некоторых старых виртуальных машин JVМ.

В приведенном выше примере программы гарантируется, что главный поток исполнения завершится последним, поскольку главный поток исполнения находится в состоянии ожидания в течение 1000 миллисекунд в промежутках между последовательными шагами цикла, а дочерний поток исполнения — только 500 миллисекунд. Это заставляет дочерний поток исполнения завершиться раньше главного потока.

Впрочем, в следующих статьях будет показано, как лучше организовать ожидание завершения потоков исполнения.