680 likes | 1.04k Views
Java Advanced. Введение в многопоточное программирование. http://kgeorgiy.info/courses/java-advanced/. Краткое содержание. Параллельное исполнение Потоки Блокировки Мониторы и события Модель памяти Java Примеры. Часть 1. Параллельное исполнение. Однозадачные системы.
E N D
Java Advanced Введение в многопоточное программирование http://kgeorgiy.info/courses/java-advanced/
Краткое содержание • Параллельное исполнение • Потоки • Блокировки • Мониторы и события • Модель памяти Java • Примеры Java Advanced / Введение в многопоточное программирование
Часть 1 Параллельное исполнение
Однозадачные системы • Одна задача за раз • Пока задача не завершилась – все ждут • Память – монопольное использование • Ввод-вывод – монопольное использование • Пока не завершилась – все ждут • Простой ресурсов • Большое время отклика Java Advanced / Введение в многопоточное программирование
Пакетные • Набор заданий для исполнения (пакет) • Память – разделяемая, изолированная • Ввод-вывод – переключение задач • Управление заданиями – монитор • Псевдопараллельное исполнение • Увеличение загрузки ресурсов • Большое время отклика • 1950-е годы Java Advanced / Введение в многопоточное программирование
Многозадачные системы • Несколько задач конкурируют за процессор • Память – разделяемая, изолированная • Прерывание – переключение задач • Ввод-вывод – разделяемый • Параллельное исполнение • Уменьшение времени отклика • 1960-е годы Java Advanced / Введение в многопоточное программирование
Многопоточные программы • Несколько задач конкурируют за процессор • Память – общая • Прерывание – переключение потоков • Ввод-вывод – разделяемый • Параллельное исполнение кода внутри программы • Уменьшение времени отклика • 1990-е годы Java Advanced / Введение в многопоточное программирование
Многопоточное программирование • Программа одновременно имеет несколько потоков исполнения • Потоки должны взаимодействовать (синхронизироваться) друг с другом Java Advanced / Введение в многопоточное программирование
Пример. Умножение матриц // Матрицы размера n на n double[][] a, b, c; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = 0; for (int k = 0; k < n; k++) { c[i][j] += a[i][k] * b[k][j]; } } } Java Advanced / Введение в многопоточное программирование
Пример. Итеративный параллелизм // Матрицы размера n на n double[][] a, b, c; for (int i = 0; i < n; i++) {// Параллельно for (int j = 0; j < n; j++) {// Параллельно c[i][j] = 0; for (int k = 0; k < n; k++) { c[i][j] += a[i][k] * b[k][j]; } } } Java Advanced / Введение в многопоточное программирование
Пример. Обмен сообщениями (1) • Рабочий поток Worker[i] { double[] a;// a[i][*] double[][] b;// b[*][*] double[] c;// c[i][*] receive a, b from coordinator; for (int j = 0; j < n; j++) { c[j] = 0; for (int k = 0; k < n; k++) { c[j] += a[k] * b[k][j]; } } send c to coordinator; } Java Advanced / Введение в многопоточное программирование
Пример. Обмен сообщениями (2) • Управляющий поток coordinator(int i) { double[][] a, b, c; for (int i = 0; i < n; i++) { send a[i], b to worker[i]; } for (int i = 0; i < n; i++) { receive c[i] from worker[i]; } } Java Advanced / Введение в многопоточное программирование
Пример. Обмен сообщениями (3) worker[i] { double[] a; // a[i][*] double[] b; // b[*][i] double[] c; // a[i][*] receive a, b from coordinator; for (int j = 0; j < n; j++) { double s = 0; for (int k = 0; k < n; k++) { s += a[k] * b[k]; } c[(i + j) % n] = s; send b to worker[(i + 1) % n]; receive b from worker[(i + n - 1) % n]; } send c to coordinator; } Java Advanced / Введение в многопоточное программирование
Пример. Вычисление интеграла • Адаптивное вычисление интеграла f(x) double integrate(double l, double r) { if (abs(area(l, m) + area(m, r) - area(l, r)) > EPS) { return integrate(l, m) + integrate(m, r); } else { return area(l, m) + area(m, r); } } double area(double l, double r) { return (f(l) + f(r)) * (r - l) / 2; } Java Advanced / Введение в многопоточное программирование
Пример. Рекурсивный параллелизм • Адаптивное вычисление интеграла f(x) double integrate(double l, double r) { double m = (l + r) / 2; double la = area(l, m); double ra = area(m, r); if (abs(la + ra - area(l, r)) > EPS) { la = integrate(l, m); // Параллельно ra = integrate(m, r); // Параллельно } return la + ra; } Java Advanced / Введение в многопоточное программирование
Основные операции • Создание потока • Уничтожение потока • Неделимая операция statements • Неделимая операцияс ожиданием условия await(C) statements Java Advanced / Введение в многопоточное программирование
Пример. Поиск максимума (1) • Без синхронизации int max = 0; create worker[i] { if (max < a[i]) max = a[i]; } • С синхронизацией int max = 0; create worker[i] { if (max < a[i]) max = a[i]; } Java Advanced / Введение в многопоточное программирование
Пример. Поиск максимума (2) • Протокол Проверить-Проверить-Установить int max = 0; create worker[i] { if (max < a[i]) { if (max < a[i]) max = a[i]; } } Java Advanced / Введение в многопоточное программирование
Свойства планирования • Безопасность • Живучесть • Справедливость • Безусловная (отсутствие условий) • Слабая • Сильная Java Advanced / Введение в многопоточное программирование
Часть 2 Потоки
Создание потоков • Класс Thread– поток • Позволяет создавать потоки и производить операции с ними • Интерфейс Runnable – сущность, которая может быть запущена • public void run(); Java Advanced / Введение в многопоточное программирование
Создание потока (Runnable) • Пример кода // Создание потока Thread t = new Thread(new Runnable() { public void run() { System.out.println("Hello"); } }); // Запуск потока t.start(); Java Advanced / Введение в многопоточное программирование
Создание потока (Thread) • Не рекомендуется использовать • Пример кода // Создание потока Thread t = new Thread() { public void run() { System.out.println("Hello"); } }; // Запуск потока t.start(); Java Advanced / Введение в многопоточное программирование
Состояния потока • Состояние потока возвращается методами • intgetState() • boolean isAlive() Java Advanced / Введение в многопоточное программирование
Свойства потока • Основные свойства • id – идентификатор потока • name – имя потока • priority – приоритет • daemon – поток-демон • Свойства потока не могут изменяться после запуска Java Advanced / Введение в многопоточное программирование
Взаимодействие потоков • Создание потока (конструктор) • Запуск потока (start) • Ожидание окончания потока (join) • Прерывание потока (interrupt) Java Advanced / Введение в многопоточное программирование
Ожидание окончания потока • Методы класса Thread • join() – ожидать до завершения • join(long millis) – ожидать до завершения или истечения millis миллисекунд • join(long millis, long nanos) – ожидать до завершения или истечения millis миллисекунди nanosнаносекунд • Все методы ожидания кидают InterruptedExcepton Java Advanced / Введение в многопоточное программирование
Прерывание потока • Методы класса Thread • interrupt() – установить флаг прерывания • isInterrupted() – проверить флаг прерывания • interrupted() – проверить и сбросить флаг прерывания • Методы, которые ожидают в процессе выполнения должны бросать InterruptedException Java Advanced / Введение в многопоточное программирование
Обработка данных в цикле class Worker implements Runnable { publicvoid run() { try { while (!Thread.interrupted()) { // Полезные действия } } catch (InterruptedException e) { } // Исполнение потока прервано // Поток заканчивает работу } } Java Advanced / Введение в многопоточное программирование
Дополнительные методы • Приостановка выполнения • sleep(time) – приостановить поток на время • yield() – позволить выполниться другим потокам • Получение текущего потока • currentThread() Java Advanced / Введение в многопоточное программирование
Часть 2 Блокировки (синхронизация)
Блокировка (lock, mutex) • Только один поток может владеть блокировкой • Операции • lock получить блокировку • unlockотдать блокировку Java Advanced / Введение в многопоточное программирование
Блокировки в Java • Любой объект может служить блокировкой • Снятие блокировки производится автоматически • Синтаксис synchronized (o) { // Получение блокировки … }// Снятие блокировки Java Advanced / Введение в многопоточное программирование
Методы экземпляра • Метод экземпляра может быть объявлен синхронизованным public synchronized int getValue() { … } • Эквивалентно public int getValue() { synchronized (this) { … } } Java Advanced / Введение в многопоточное программирование
Методы класса • Метод класса может быть объявлен синхронизованным Class Example { public static synchronized int getValue() { … } • Эквивалентно public int getValue() { synchronized (Example.class) { … } } Java Advanced / Введение в многопоточное программирование
Производитель-потребитель • Один поток производит данные, второй их потребляет • Несколько потоков производят данные и несколько их потребляют • Данные могут храниться в очереди (не)ограниченного объема Java Advanced / Введение в многопоточное программирование
Интерфейс очереди • Хранит один элемент class Queue { private Object data; public void set(Object data) { … } public Object get() { … } } Java Advanced / Введение в многопоточное программирование
Производитель • Установка значения public void set(Object data) { while (true) {// Активное ожидание synchronized (this) { if (data == null) { this.data = data; break; } } } } Java Advanced / Введение в многопоточное программирование
Потребитель • Получение значения public Object get() { while (true) {// Активное ожидание synchronized (this) { if (data != null) { Object d = data; data = null; return d; } } } } Java Advanced / Введение в многопоточное программирование
Часть 3 Мониторы и условия
Монитор • Любой объект может быть монитором • Передача событий • wait(time?)– ожидание условия • notify() – извещение одного из ждущих потоков • notifyAll() – извещение всех ждущих потоков • Нужно владеть блокировкой • IllegalMonitorStateException Java Advanced / Введение в многопоточное программирование
Мониторы и блокировки • При ожидании монитора блокировка с него снимается • При извещении поток не получает управления пока не может получить блокировку обратно • Псевдокод monitor.unlock() monitor.await() monitor.lock() Java Advanced / Введение в многопоточное программирование
Производитель (2) • Установка значения public synchronized void set(Object data) throws InterruptedException { while (data != null) { wait();// Пассивное ожидание } this.data = data; notify(); } Java Advanced / Введение в многопоточное программирование
Потребитель (2) • Получение значения public synchronized Object get() throws InterruptedException { while (data == null) { wait(); // Пассивное ожидание } Object d = data; data = null; notify(); return d; } Java Advanced / Введение в многопоточное программирование
notify() и notifyAll() • События одного вида • Может обработать любой ждущий поток • notify() • Несколько видов событий • Побуждение «Не того» потока • notifyAll() • Более дорогая операция Java Advanced / Введение в многопоточное программирование
Внезапные пробуждения • wait()может завершиться без notify() • Проверить наступление события • Ожидать всегда в цикле • Идиома • while (дождался)wait(); Java Advanced / Введение в многопоточное программирование
Часть 4 Модель памяти Java
Основные свойства • Атомарность • Видимость • Упорядоченность Java Advanced / Введение в многопоточное программирование
Атомарность • Атомарная операция выполняется как единое целое • Операции над всеми типами кроме longи doubleявляются атомарными Java Advanced / Введение в многопоточное программирование
int a = 0; long b = 0; // T1 a = 1; b = -1; Возможные значения a 0 1 Возможные значения b 0 -1 0xffffffff00000000 0x00000000ffffffff … Пример Java Advanced / Введение в многопоточное программирование