
- •Харьковский Национальный Университет Радиоэлектроники Кафедра Инфокоммуникационной инженерии
- •Содержание
- •Литература
- •Процессы и потоки
- •Многопоточное программирование
- •Класс Thread
- •Создание и запуск потока
- •Создание и запуск потока
- •Создание и запуск потока
- •Thread vs Runnable
- •Более наглядный пример:
- •Как работает многопоточность
- •Методы Start( ) и Run( )
- •Каждому потоку свой стек
- •Главный поток
- •Имя, приоритет и группа потока
- •Управление потоками. Метод Sleep( )
- •Управление потоками. Метод Sleep( )
- •Управление потоками. Метод Join( )
- •Прерывание потока
- •Асинхронное выполнение
- •Асинхронное выполнение
- •Потоки-демоны
- •Потоки-демоны
- •Базовые состояния потока
- •Два состояния работающего потока в ОС
- •Когда использовать потоки
- •Вопросы ?
Харьковский Национальный Университет Радиоэлектроники Кафедра Инфокоммуникационной инженерии
Потоки выполнения (ч. 1) (Threads)
Доцент кафедри ИКИ Евдокименко Марина Александровна
2017

Содержание
1.Введение в потоки.
2.Создание потоков.
3.Управление и контроль жизненного цикла потока.
Литература
1.Герберт Шилдт "Java 7. Полное руководство" (8-е издание) Гл. 11. стр. 259-288.
2.Oracle Certified Professional Java SE 7 Programmer Exams 1Z0-804 and 1Z0-805: A Comprehensive OCPJP 7 Certification Guide. Гл. 13. стр. 393-430.
Процессы и потоки
В параллельном программировании, существуют две основные единицы исполнения: процессы и потоки. В Java, параллельное программирование в основном связано с потоками. Тем не менее, процессы также важны.
Процесс имеет автономную среду исполнения. Обычно имеет отдельный набор базовых ресурсов времени выполнения, в частности, каждый процесс имеет свое собственное пространство памяти.
Поток выполнения (англ. Thread - нить) — наименьшая единица обработки, исполнение которой может быть назначено ядром операционной системы. Это независимый путь исполнения, способный выполняться одновременно с другими потоками.
Реализация потоков выполнения и процессов в разных операционных системах отличается друг от друга, но в большинстве случаев поток выполнения находится внутри
процесса.
Несколько потоков выполнения могут существовать в рамках одного и того же процесса и совместно использовать ресурсы, такие как память, тогда как процессы не разделяют этих ресурсов. В частности, потоки выполнения разделяют инструкции процесса (его код) и его контекст (значения переменных, которые они имеют в любой момент времени).
В качестве аналогии потоки выполнения процесса можно уподобить нескольким вместе работающим поварам. Все они готовят одно блюдо, читают одну и ту же кулинарную книгу с одним и тем же рецептом и следуют его указаниям, причём не обязательно все они читают на одной и той же странице.
Многопоточное программирование
Java предлагает встроенную поддержку многопоточного программирования.
Фактически Java использует потоки для того, чтобы обеспечить асинхронность всей среде выполнения. Это позволяет снизить неэффективность за счет предотвращения холостой растраты циклов центрального процессора.
Однопоточные системы используют подход, называемый циклом событий с опросом. В этой модели единственный поток управления выполняется в бесконечном цикле, опрашивая единственную очередь событий, чтобы принять решение о том, что делать дальше. Это расходует время процессора. Это также может привести к тому, что одна часть программы будет доминировать над другими и не давать возможности обрабатывать любые другие события.
Выгода от многопоточности состоит в том, что основной механизм циклического опроса исключается. Один поток может быть приостановлен без остановки других частей программы. Например, время ожидания при чтении данных из сети либо ожидание пользовательского ввода может быть утилизировано где угодно. Многопоточность позволяет циклам анимации "засыпать" на секунду между показом соседних кадров, не приостанавливая работы всей системы. Когда поток блокируется в программе Java, то останавливается только один-единственный заблокированный поток. Все остальные потоки продолжают выполняться.
Потоки существуют в нескольких состояниях. Поток может выполняться. Он может быть готов к выполнению, как только получит время центрального процессора. Работающий поток может быть приостановлен, что временно прекращает его активность. Выполнение приостановленного потока может быть возобновлено, позволяя ему продолжить работу с того места, где он был приостановлен. Поток может быть заблокирован, когда ожидает какого-то ресурса. В любой момент поток может быть прерван, что немедленно останавливает его выполнение. Однажды прерванный поток уже не может быть возобновлен.

Класс Thread
Каждый поток в Java связан с экземпляром класса Thread. Ниже представлены основные методы этого класса:

Создание и запуск потока
В Java существует два способа создания и запуска потока:расширение класса Thread
реализация интерфейса Runnable.
Расширение класса Thread

Создание и запуск потока
Запущен главный поток
главный поток |
JVM порождает новый поток |
||
и вызывает метод run() |
|||
продолжает |
|||
выполнение |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
На рисунке показано, как выполняется эта программа. Отметим, что основной поток и поток myThread1 выполняются одновременно (т.е. параллельно), как показано на схеме. Если вы запустите эту программу пару раз, вы либо получите результат, показанный выше, или порядок этих двух выводимых утверждений может поменяться (в зависимости от того, какой поток запланирован первый для выполнения этого). Недетерминированное поведение будет рассмотрено чуть позже.

Создание и запуск потока
Реализация интерфейса Runnable
При реализации интерфейса Runnable необходимо определить его единственный абстрактный метод run(). Например:

Thread vs Runnable
Почему Java предлагает два способа создания дочерних потоков и какой из них лучше?
Класс Thread определяет несколько методов, которые могут быть переопределены в производных классах. Из этих методов только один должен быть переопределен в обязательном порядке — это метод run(). Конечно, этот же метод нужен, когда вы реализуете интерфейс Runnable.
Многие программисты Java считают, что классы следует расширять только в случаях, когда они должны быть усовершенствованы или некоторым образом модифицированы. Поэтому если вы не переопределяете никаких других методов класса Thread, то вероятно, лучше просто реализовать интерфейс Runnable.
Кроме того, при реализации интерфейса Runnable ваш класс потока не должен наследовать класс Thread, таким образом он может унаследовать какой-либо другой класс. Этот аргумент тоже в пользу реализации Runnable.
В случае реализации интерфейса Runnable для того чтобы вызвать соответствующие методы экземпляра класса Thread нужно использовать более громоздкий сиснаксис, например: Thread.currentThread().getName() в отличии от случая наследования класса Thread где достаточно вызвать этот метод - getName().
В конечном счете, это два равноценных способа создания. Какой из подходов использовать, остается на ваше усмотрение.