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

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

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

public void run()

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

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

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

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

Thread(Runnable _, String _)

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

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

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

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

void start()

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

//    

class NewThread implements Runnable {
    
    Thread t;
    
    NewThread() {
        
        //  ,   
        t = new Thread(this, " ");
        System.out.println("  : " + t);
        t.start(); //   
        
    }
    
    //      
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println(" : " + i);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("  .");
        }
        System.out.println("  .");
    }
    
}

class ThreadDemo {
    
    public static void main(String args[]) {
        
        new NewThread(); //   
        
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println(" : " + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("  .");
        }
        System.out.println("  .");
        
        
    }
    
}

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

t = new Thread(this, " ");

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

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

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

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

  : hrd [  , 5, min ]
  : 5
  : 5
  : 4
  : 4
  : 3
  : 2
  : 3
  : 1
  .
  : 2
  : 1
  .

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

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

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

Один комментарий на “Реализация интерфейса runnable Java

  1. Привет!
    Подскажите, а если внутри конструктора NewThread() мы НЕ будем вызывать new Thread(this, “Демонстрационный поток”) и потом внутри public static void main обратимся напрямую new NewThread().RUN() – то новой нити не создастся и сперва главная нить отработает логику NewThread(), а потом эта же нить отработку логику цикла внутри System.out.println(“Главный поток: ” + i);

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *