Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения
Имеется два способа создать класс, экземплярами которого будут потоки выполнения: унаследовать класс от java.lang.Thread либо реализовать интерфейс java.lang.Runnable. Этот интерфейс имеет декларацию единственного метода public void run(), который обеспечивает последовательность действий при работе потока. При этом класс Thread уже реализует интерфейс Runnable, но с пустой реализацией метода run().Так что при создании экземпляра Thread создаётся поток, который ничего не делает. Поэтому в потомке надо переопределить метод run(). В нём следует написать реализацию алгоритмов, которые должны выполняться в данном потоке. Отметим, что после выполнения метода run() поток прекращает существование – “умирает”.
Рассмотрим первый вариант, когда мы наследуем класс от класса Thread , переопределив метод run().
Объект-поток создаётся с помощью конструктора. Имеется несколько перегруженных вариантов конструкторов, самый простой из них – с пустым списком параметров. Например, в классе Thread их заголовки выглядят так:
public Thread() – конструктор по умолчанию. Подпроцесс получает имя “system”.
public Thread(String name) - поток получает имя, содержащееся в строке name.
Также имеется возможность создавать потоки в группах. Но в связи с тем, что данная технология устарела и не нашла широкого распространения, о группах потоков выполнения в данном учебном пособии рассказываться не будет.
В классе-потомке можно вызывать конструктор по умолчанию (без параметров), либо задать свои конструкторы, используя вызовы прародительских с помощью вызова super(список параметров). Из-за отсутствие наследования конструкторов в Java приходится в наследнике заново задавать конструкторы с той же сигнатурой, что и в классе Thread. Это является простой, но утомительной работой. Именно поэтому обычно предпочитают способ задания класса с реализацией интерфейса Runnable, о чём будет рассказано несколькими строками позже.
Создание и запуск потока осуществляется следующим образом:
public class T1 extends Thread{
public void run(){
...
}
...
}
Thread thread1= new T1();
thread1.start();
Второй вариант – использование класса, в котором реализован интерфейс java.lang.Runnable. Этот интерфейс, как уже говорилось, имеет единственный метод public void run(). Реализовав его в классе, можно создать поток с помощью перегруженного варианта конструктора Thread:
public class R1 implements Runnable{
public void run(){
...
}
...
}
Thread thread1= Thread( new R1() );
thread1.start();
Обычно таким способом пользуются гораздо чаще, так как в разрабатываемом классе не приходится заниматься дублированием конструкторов класса Thread. Кроме того, этот способ можно применять в случае, когда уже имеется класс, принадлежащий иерархии, в которой базовым классом не является Thread или его наследник, и мы хотим использовать этот класс для работы внутри потока. В результате от этого класса мы получаем метод run(), в котором реализован нужный алгоритм, и этот метод работает внутри потока типа Thread, обеспечивающего необходимое поведение в многопоточной среде. Однако в данном случае затрудняется доступ к методам из класса Thread – требуется приведение типа.
Например, чтобы вывести информацию о приоритете потока, в первом способе создания потока в методе run() надо написать оператор
System.out.println("Приоритет потока="+this.getPriority());
А во втором способе приходиться это делать в несколько этапов. Во-первых, при задании класса нам следует добавить в объекты типа R1 поле thread:
public class R1 implements Runnable{
public Thread thread;
public void run() {
System.out.println("Приоритет потока="+thread.getPriority());
}
}
С помощью этого поля мы будем добираться до объекта-потока. Но теперь после создания потока необходимо не забыть установить для этого поля ссылку на созданный объект-поток. Так что создание и запуск потока будет выглядеть так:
R1 r1=new R1();
Thread thread1=new Thread(r1, "thread1");
r1.thread=thread1;
thread1.start();//либо, что то же, r1.thread.start()
Через поле thread мы можем получать доступ к потоку и всем его полям и методам в алгоритме, написанном в методе run(). Указанные выше дополнительные действия – это всего три лишних строчки программы (первая - R1 r1=new R1(); вторая - r1.thread=thread1; третья - объявление в классе R1 - public Thread thread;) .
Как уже говорилось ранее, напрямую давать доступ к полю данных – дурной тон программирования. Исправить этот недостаток нашей программы просто: в дереве элементов программы окна Projects в разделе Fields (“поля”) щёлкнем правой кнопкой мыши по имени thread и выберем в появившемся всплывающем меню Refactor/Encapsulate Fields… (“Провести рефакторинг”/ “Инкапсулировать поля…”). В появившемся диалоге нажмём на кнопку “Next>” и проведём рефакторинг, подтвердив выбор в нижнем окне.
В классе Thread имеется несколько перегруженных вариантов конструктора с параметром типа Runnable:
public Thread(Runnable target) – с именем “system” по умолчанию.
public Thread(Runnable target, String name) – с заданием имени.
Также имеются варианты с заданием группы потоков.
- Содержание
- Глава 1. Общие представления о языке Java 6
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans 26
- Глава 3. Примитивные типы данных и операторы для работы с ними 78
- Глава 4. Работа с числами в языке Java 95
- Глава 5. Управляющие конструкции 112
- Глава 6. Начальные сведения об объектном программировании 128
- Глава 7. Важнейшие объектные типы 175
- Введение
- Глава 1. Общие представления о языке Java
- 1.1. Java и другие языки программирования. Системное и прикладное программирование
- 1.2. Виртуальная Java-машина, байт-код, jit-компиляция. Категории программ, написанных на языке Java
- 1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова Алфавит языка Java
- Десятичные и шестнадцатеричные цифры и целые числа
- Зарезервированные слова языка Java
- 1.4. Управляющие последовательности. Символы Unicode. Специальные символы Управляющие последовательности
- Простые специальные символы
- Составные специальные символы
- 1.5.Идентификаторы. Переменные и типы. Примитивные и ссылочные типы
- Краткие итоги по главе 1
- Задания
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans
- 2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция
- 2.2. Работа со ссылочными переменными. Сборка мусора
- 2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов
- 2.4. Базовые пакеты и классы Java
- 2.5. Создание в NetBeans простейшего приложения Java
- 2.6. Компиляция файлов проекта и запуск приложения
- 2.7. Структура проекта NetBeans
- 2.8. Создание в NetBeans приложения Java с графическим интерфейсом
- 2.9. Редактор экранных форм
- 2.10. Внешний вид приложения
- 2.11. Ведение проектов
- 2.11. Редактирование меню экранной формы
- 2.12. Создание нового класса
- 2.13. Документирование исходного кода в Java
- 2.14. Основные компоненты пакетов swing и awt
- 2.15. Технологии Java и .Net
- Краткие итоги по главе 2
- Задания
- Глава 3. Примитивные типы данных и операторы для работы с ними
- 3.1.Булевский (логический) тип
- 3.2.Целые типы, переменные, константы
- 3.3.Основные операторы для работы с целочисленными величинами
- 3.4.Вещественные типы и класс Math
- 3.5.Правила явного и автоматического преобразования типа при работе с числовыми величинами
- 3.6. Оболочечные классы. Упаковка (boxing) и распаковка (unboxing)
- 3.7.Приоритет операторов
- 3.8.Типы-перечисления (enum)
- Краткие итоги по главе 3
- Задания
- Глава 4. Работа с числами в языке Java
- 4.1 Двоичное представление целых чисел Позиционные и непозиционные системы счисления
- Двоичное представление положительных целых чисел
- Двоичное представление отрицательных целых чисел. Дополнительный код
- Проблемы целочисленной машинной арифметики
- Шестнадцатеричное представление целых чисел и перевод из одной системы счисления в другую
- 4.2. Побитовые маски и сдвиги
- 4.3. Двоичное представление вещественных чисел Двоичные дроби
- Мантисса и порядок числа
- Стандарт ieee 754 представления чисел в формате с плавающей точкой*
- Краткие итоги по главе 4
- Задания
- Глава 5. Управляющие конструкции Составной оператор
- Условный оператор if
- Оператор выбора switch
- Условное выражение …?... : …
- Оператор цикла for
- Оператор цикла while – цикл с предусловием
- Оператор цикла do...While – цикл с постусловием
- Операторы прерывания continue, break, return, System.Exit
- Краткие итоги по главе 5
- Задания
- Глава 6. Начальные сведения об объектном программировании
- Наследование и полиморфизм. Uml-диаграммы
- Функции. Модификаторы. Передача примитивных типов в функции
- Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this
- Передача ссылочных типов в функции. Проблема изменения ссылки внутри подпрограммы
- Наследование. Суперклассы и подклассы. Переопределение методов
- Наследование и правила видимости. Зарезервированное слово super
- Статическое и динамическое связывание методов. Полиморфизм
- Базовый класс Object
- Конструкторы. Зарезервированные слова super и this. Блоки инициализации
- Удаление неиспользуемых объектов и метод finalize. Проблема деструкторов для сложно устроенных объектов
- Перегрузка методов
- Правила совместимости ссылочных типов как основа использования полиморфного кода. Приведение и проверка типов
- Рефакторинг
- Reverse engineering – построение uml-диаграмм по разработанным классам
- Краткие итоги по главе 6
- Задания
- Глава 7. Важнейшие объектные типы Массивы
- Коллекции, списки, итераторы
- Работа со строками в Java. Строки как объекты. Классы String, StringBuffer и StringBuilder
- Работа с графикой
- Исключительные ситуации Обработка исключительных ситуаций
- Иерархия исключительных ситуаций
- Объявление типа исключительной ситуации и оператор throw
- Объявление метода, который может возбуждать исключительную ситуацию. Зарезервированное слово throws
- Работа с файлами и папками
- Краткие итоги по главе 7
- Задания
- Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция Проблемы множественного наследования классов. Интерфейсы
- Отличия интерфейсов от классов. Проблемы наследования интерфейсов
- Пример на использование интерфейсов
- Композиция как альтернатива множественному наследованию
- Краткие итоги по главе 8
- Задания
- Глава 9. Дополнительные элементы объектного программирования на языке Java Потоки выполнения (threads) и синхронизация
- Преимущества и проблемы при работе с потоками выполнения
- Синхронизация по ресурсам и событиям
- Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения
- Поля и методы, заданные в классе Thread
- Подключение внешних библиотек dll.“Родные” (native) методы*
- Краткие итоги по главе 9
- Задания
- Глава 10. Введение в сетевое программирование Краткая справка по языку html
- Апплеты
- Сервлеты
- Технология jsp – Java Server Pages
- Краткие итоги по главе 10
- Задания
- Глава 11. Встроенные классы Виды встроенных классов
- Вложенные (nested) классы и интерфейсы
- Внутренние (inner) классы
- Локальные (local) классы
- Анонимные (anonimous) классы и обработчики событий
- Анонимные (anonimous) классы и слушатели событий (listeners)
- Краткие итоги по главе 11
- Задания
- Глава 12. Компонентное программирование Компонентная архитектура JavaBeans
- Мастер создания компонента в NetBeans
- Пример создания компонента в NetBeans – панель с заголовком
- Добавление в компонент новых свойств
- Добавление в компонент новых событий
- Краткие итоги по главе 12
- Задания
- Литература
- Дополнительная литература
- 276 Курс подготовлен при поддержке Sun Microsystems