МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ В JAVA Пакеты java.lang java.util.concurrent.

Презентация:



Advertisements
Похожие презентации
Многопоточное программирование на Java Java Advanced.
Advertisements

Многопоточное программирование на Java Java Advanced.
Введение в многопоточное программирование Java Advanced
Параллелизм и потоки в Java For students of university Author: Oxana Dudnik.
Обеспечение эффективной многопоточности Java приложений Андрей Дмитриев Ноябрь 2009.
1 Java 14. Параллельное выполнение. 2 Терминология При переводе на русский ДВА английских термина имеют одинаковое значение – поток: stream thread Thread.
ПОТОКИ Начальные сведенияПОТОКИ Начальные сведения.
Хранение данных (1) Для того, чтобы выяснить, откуда берутся гонки данных, нужно разобраться в том, как обеспечивается хранение данных приложения и его.
Модель приложений.NET. Среда платформы Win32, в которой выполняется программа, называется ее процессом. Эта среда состоит из: адресного пространства,
Лекция 6 Взаимоблокировка потоков Если имеются два потока и два объекта, подлежащих блокированию, возникает опасность возникновения взаимоблокировки каждый.
Синтаксис языка Java. Символы и синтаксис Перевод строчки эквивалентен пробелу Регистр в именах различается.
Лекция 5 Шаблоны в Java В Java можно использовать шаблоны классов. Рассмотрим пример класса - шаблона: public class Pair { public Pair(T f, S s) { first.
Новосибирск, 2004 (С) Всеволод Рылов, все права защищены 1 Основы программирования на языке Java Стандартная библиотека Java: java.net; Многопоточное программирование.
Java SE: основные понятия Борис Кварцхава
СОБЫТИЯ Лекция 1. Взаимодействие объектов 2 Взаимодействие между объектами A и B можно организовать двумя способами. 1.Объект A вызывает метод объекта.
Многопоточное программирование Java Advanced. 2Georgiy Korneev Краткое содержание 1.Введение 2.Классические задачи многопоточного программирования 3.Атомарные.
POSIX Threads. Общая модель Программа Общая память Поток 1 CPU Поток 2 Поток N Потоки – наборы инструкций, исполняющиеся на CPU. Все потоки одной программы.
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Многопоточные приложения в Java Лекция 8. Многопоточность Многопоточность операционной системы – возможность одновременного выполнения более чем одной.
Многопоточное программирование Синхронизация потоков Лекция 11.
Транксрипт:

МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ В JAVA Пакеты java.lang java.util.concurrent

ЧАСТЬ 1 ВВЕДЕНИЕ

ПОТОКИ Каждый поток имеет свой стек вызовов У потоков общая память! Java-поток != поток в ОС У JVM свой планировщик потоков, который не зависит от планировщика операционной системы под которой работает JVM В Java есть два вида потоков: потоки-демоны (daemon threads) и пользовательские потоки (user threads). JVM завершает выполнение программы когда все пользовательские потоки завершат свое выполнение. Java Advanced / Threads

СОЗДАНИЕ ПОТОКОВ Класс Thread – поток Позволяет создавать потоки и производить операции с ними Интерфейс Runnable – сущность, которая может быть запущена public void run();

СОЗДАНИЕ ПОТОКА (RUNNABLE) Пример кода // Создание потока Thread t = new Thread(new Runnable() { public void run() { System.out.println("Hello"); } }); // Запуск потока t.start(); Java Advanced / Threads

СОЗДАНИЕ ПОТОКА (THREAD) Не рекомендуется использовать Пример кода // Создание потока Thread t = new Thread() { public void run() { System.out.println("Hello"); } }; // Запуск потока t.start(); Java Advanced / Threads

ИНСТАНЦИРОВАНИЕ ПОТОКА Если вы расширили класс Thread: MyThread t = new MyThread(); Если вы реализовывали Runnable: MyRunnable r = new MyRunnable(); Thread t = new Thread(r); Один экземпляр Runnable можно передать нескольким объектам Thread: MyRunnable r = new MyRunnable(); Thread foo = new Thread(r); Thread bar = new Thread(r); Thread bat = new Thread(r); Java Advanced / Threads

КОНСТРУКТОР THREAD Thread() Thread(String name) Thread(Runnable runnable) Thread(Runnable runnable, String name) … Java Advanced / Threads

ЗАПУСК ПОТОКА Нужно так: t.start(); НЕ ТАК: t.run(); Java Advanced / Threads

ПРИМЕР public class Starter { public static void main(String[] args) { NameRunnable nr = new NameRunnable(); Thread one = new Thread(nr); Thread two = new Thread(nr); Thread three = new Thread(nr); one.setName("Первый"); two.setName("Второй"); three.setName("Третий"); one.start(); two.start(); three.start(); } class NameRunnable implements Runnable { public void run() { for (int x = 1; x

СВОЙСТВА ПОТОКА Основные свойства id – идентификатор потока name – имя потока priority – приоритет daemon – поток-демон Свойства потока не могут изменяться после запуска Java Advanced / Threads

СОСТОЯНИЯ ПОТОКА Состояние потока возвращается методами int getState() boolean isAlive()

СОСТОЯНИЯ ПОТОКА Поток может находиться в одном из пяти состояний: Новый (new). После создания экземпляра потока, он находится в состоянии Новый до тех пор, пока не вызван метод start(). В этом состоянии поток не считается живым. Работоспособный (runnable). Поток переходит в состояние Работоспособный, когда вызывается метод start(). Поток может перейти в это состояние также из состояния Работающий или из состояния Блокирован. Работающий (running). Поток переходит из состояния Работоспособный в состояние Работающий, когда Планировщик потоков выбирает его из runnable pool как работающий в данный момент. Ожидающий (waiting)/ Заблокированный (blocked)/ Спящий (sleeping). Эти состояния характеризуют поток как не готовый к работе. Мёртвый ( dead ). Java Advanced / Threads

СОСТОЯНИЯ ПОТОКА Java Advanced / Threads

ВЗАИМОДЕЙСТВИЕ ПОТОКОВ Создание потока Запуск потока (start) Ожидание окончания потока (join) Прерывание потока (interrupt) Засыпание потока (sleep) Переключение потоков (yield) Java Advanced / Threads

ОТПРАВКА В СОН Thread.sleep(millis, nanos) TimeUnit.SECONDS.sleep(secs) Перечисление TimeUnit SECONDS MILLISECONDS MICROSECONDS NANOSECONDS DAYS HOURS MINUTES Все методы кидают InterruptedExcepton Java Advanced / Threads

ПРИОРИТЕТЫ И YIELD Приоритеты: Thread.MIN_PRIORITY (1) Thread.NORM_PRIORITY (5) Thread.MAX_PRIORITY (10) FooRunnable r = new FooRunnable(); Thread t = new Thread(r); t.setPriority(8); t.start(); Метод yield() можно использовать для того чтобы предложить планировщику выполнить другой поток, который ожидает своей очереди. Java Advanced / Threads

БЛОКИРОВКА ДРУГОГО ПОТОКА Методы sleep и yield – статические! И действуют на текущий поток! Приостановить работу другого потока нельзя. Java Advanced / Threads

ОЖИДАНИЕ ОКОНЧАНИЯ ПОТОКА Методы класса Thread join() – ожидать до завершения join(long millis) – ожидать до завершения или истечения millis миллисекунд join(long millis, long nanos) – ожидать до завершения или истечения millis миллисекунд и nanos наносекунд Все методы ожидания кидают InterruptedExcepton Thread t = new Thread(); t.start(); t.join(); Java Advanced / Threads

ПРЕРЫВАНИЕ ПОТОКА Методы класса Thread interrupt() – установить флаг прерывания isInterrupted() – проверить флаг прерывания interrupted() – проверить и сбросить флаг прерывания Методы, которые ожидают в процессе выполнения должны бросать InterruptedException Java Advanced / Threads

ОБРАБОТКА ДАННЫХ В ЦИКЛЕ class Worker implements Runnable { public void run() { try { while (!Thread.interrupted()) { // Полезные действия } } catch (InterruptedException e) { } // Исполнение потока прервано // Поток заканчивает работу } Java Advanced / Threads

ЧАСТЬ - 2 СИНХРОНИЗАЦИЯ КОДА Java Advanced / Threads

БЛОКИРОВКИ В JAVA Любой объект может служить блокировкой Снятие блокировки производится автоматически Синтаксис synchronized (o) { // Получение блокировки … } // Снятие блокировки Java Advanced / Threads

МЕТОДЫ ЭКЗЕМПЛЯРА Метод экземпляра может быть объявлен синхронизованным public synchronized int getValue() { … } Эквивалентно (почти) public int getValue() { synchronized (this) { … } } Java Advanced / Threads

МЕТОДЫ КЛАССА Метод класса может быть объявлен синхронизованным Class Example { public static synchronized int getValue() { … } Эквивалентно public int getValue() { synchronized (Example.class) { … } } Java Advanced / Threads

УДЕРЖИВАНИЕ БЛОКИРОВОК При вызове yield, sleep, join поток удерживает все свои блокировки! Java Advanced / Threads

ПРИМЕР ПРОИЗВОДИТЕЛЬ-ПОТРЕБИТЕЛЬ Один поток производит данные, второй их потребляет Несколько потоков производят данные и несколько их потребляют Данные могут храниться в очереди (не)ограниченного объема Java Advanced / Threads

ИНТЕРФЕЙС ОЧЕРЕДИ Хранит один элемент class Queue { private Object data; public void set(Object data) { … } public Object get() { … } } Java Advanced / Threads

ПРОИЗВОДИТЕЛЬ Установка значения public void set(Object data) { while (true) { // Активное ожидание synchronized (this) { if (this.data == null) { this.data = data; break; } Java Advanced / Threads

ПОТРЕБИТЕЛЬ Получение значения public Object get() { while (true) { // Активное ожидание synchronized (this) { if (data != null) { Object d = data; data = null; return d; } Java Advanced / Threads

ЧАСТЬ 3 МОНИТОРЫ И УСЛОВИЯ Java Advanced / Threads

ВЗАИМОДЕЙСТВИЕ ПОТОКОВ В классе Object есть три метода wait(), notify(), notifyAll(), которые позволяют потоку сообщать информацию о своем состоянии другим, заинтересованным в этой информации, потокам. Java Advanced / Threads

МОНИТОРЫ Любой объект может быть монитором Передача событий wait(time?) – ожидание условия notify() – извещение одного из ждущих потоков notifyAll() – извещение всех ждущих потоков Нужно владеть блокировкой IllegalMonitorStateException Java Advanced / Threads

МОНИТОРЫ При ожидании монитора (wait) блокировка с него снимается При извещении поток не получает управления пока не может получить блокировку обратно notify() и notifyAll() не снимают блокировку! Java Advanced / Threads

ПРОИЗВОДИТЕЛЬ (1) Установка значения public synchronized void set(Object data) throws InterruptedException { if (this.data != null) { wait(); // Пассивное ожидание } this.data = data; notify(); } Java Advanced / Threads

ПОТРЕБИТЕЛЬ (1) Получение значения public synchronized Object get() throws InterruptedException { if (data == null) { wait(); // Пассивное ожидание } Object d = data; data = null; notify(); return d; } Java Advanced / Threads

ПРОИЗВОДИТЕЛЬ (2) Установка значения public synchronized void set(Object data) throws InterruptedException { while (this.data != null) { wait(); // Пассивное ожидание } this.data = data; notify(); } Java Advanced / Threads

ПОТРЕБИТЕЛЬ (2) Получение значения public synchronized Object get() throws InterruptedException { while (data == null) { wait(); // Пассивное ожидание } Object d = data; data = null; notify(); return d; } Java Advanced / Threads

ВНЕЗАПНЫЕ ПРОБУЖДЕНИЯ wait() может завершиться без notify() Проверить наступление события Ожидать всегда в цикле Идиома while (дождался) wait(); Java Advanced / Threads

ЗАДАНИЯ-РАБОТНИКИ Поток-клиент ждет выполнения задания потоком- сервером Java Advanced / Threads

ЗАДАНИЯ-РАБОТНИКИ Решение с помощью монитора Задание queue.add(task); queue.notify(); task.wait(); Работник while (queue.isEmpty()) queue.wait(); Task t = queue.get(); // Обработка задания t.notify(); Java Advanced / Threads

NOTIFYALL() public class Reader extends Thread { Calculator c; public Reader(Calculator calc) { c = calc; } public void run() { synchronized (c) { try { System.out.println("Вычисление..."); c.wait(); } catch (InterruptedException e) { } System.out.println("Total равно: " + c.total); } public static void main(String[] args) { Calculator calculator = new Calculator(); new Reader(calculator).start(); new Reader(calculator).start(); new Reader(calculator).start(); calculator.start(); } class Calculator extends Thread { int total; public void run() { synchronized (this) { for (int i = 0; i < 100; i++) { total += i; } notifyAll(); } Java Advanced / Threads

JAVA MEMORY MODEL Java Advanced / Threads

ОСНОВНЫЕ СВОЙСТВА Атомарность Видимость Упорядоченность Java Advanced / Threads

АТОМАРНОСТЬ Атомарная операция выполняется как единое целое Операции над всеми типами кроме long и double являются атомарными Java Advanced / Threads

ПРИМЕР Java Advanced / Threads int a = 0; long b = 0; // T1 a = 1; b = -1; Возможные значения a 0 1 Возможные значения b 0 0xffffffff x ffffffff …

ВИДИМОСТЬ Изменения произведенные потоком 1 видимы потоком 2 Видимость гарантируется в следующих случаях После изменений поток 1 освободил блокировку, которую захватил поток 2 После изменения поток 1 создал поток 2 Поток 2 дождался окончания потока 1 При неправильной синхронизации изменения могут быть видимы в произвольном порядке Java Advanced / Threads

ПРИМЕР Java Advanced / Threads int a = 0; int b = 0; // T1 a = 1; b = 2; Возможные значения пары а, b 0, 0 1, 0 1, 2 0, 2

УПОРЯДОЧЕННОСТЬ Программы выполняются как если бы они были написаны последовательно С точки зрения других потоков выполнение программы может производиться в произвольном порядке Java Advanced / Threads

ПРИМЕР Java Advanced / Threads int a = 0; a = 1; a = 2; Возможные последовательности значений а 0, 0 0, 1 0, 2 1, 2 2, 0 2, 1 …

VOLATILE-ПЕРЕМЕННЫЕ Операции с volatile-переменными всегда атомарны При чтение значения volatile-переменной оно всегда читается из общей памяти При записи значения volatile-переменной оно всегда записывается в общую память Если volatile-ссылка изменилась, то данные доступные по ней могли не измениться Java Advanced / Threads

ПРО SINGLETON // Однопоточная версия class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) helper = new Helper(); return helper; } // и остальные члены класса… } Java Advanced / Threads

ПРО SINGLETON // Правильная, но "дорогая" по времени выполнения многопоточная версия class Foo { private Helper helper = null; public synchronized Helper getHelper() { if (helper == null) helper = new Helper(); return helper; } // и остальные члены класса… } Java Advanced / Threads

ПРО SINGLETON // Неработающая многопоточная версия // Шаблон "Double-Checked Locking" class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) { helper = new Helper(); } return helper; } // и остальные члены класса… } Java Advanced / Threads

ПРО SINGLETON // Работает с новой семантикой volatile // Не работает в Java 1.4 и более ранних версиях из-за семантики volatile class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } // и остальные члены класса… } Java Advanced / Threads

ПРО SINGLETON public class Singleton { private Singleton() {} private static class SingletonHolder { public static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } Java Advanced / Threads

ПРО SINGLETON public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } Java Advanced / Threads

ПРО SINGLETON public class Singleton { private static final Singleton instance; static { try { instance = new Singleton(); } catch (IOException e) { throw new RuntimeException("Darn, an error occurred!", e); } public static Singleton getInstance() { return instance; } private Singleton() { //... } Java Advanced / Threads