
- •Многопоточное программирование
- •Цели занятия
- •Понятие многопоточности
- •Реализация многопоточности
- •Реализация многопоточности
- •Особенности многопоточности
- •Использование класса Thread
- •Использование класса Thread
- •Использование класса Thread
- •Использование интерфейса
- •Использование интерфейса
- •Управление потоками
- •Нерекомендуемые действия над
- •Группы потоков
- •Группы потоков
- •Операции в группе потоков
- •Приоритеты потоков
- •Приоритеты потоков
- •Демон-потоки
- •Демон-группы потоков
- •Совместное использование
- •Совместное использование
- •Совместное использование
- •Совместное использование
- •Характерные ошибки
- •volatile
- •volatile
- •Специальные методы класса
- •Особенности использования
- •Прерывание потока
- •Пример
- •Пример
- •Пример
- •java.util.concurrent
- •java.util.concurrent
- •java.util.concurrent.locks
- •Lock Objects
- •ReentrantLock
- •Пример ReentrantLock
- •ReadWriteLock
- •Пример ReadWriteLock
- •Исполнители (Executors)
- •Интерфейсы исполнителей
- •Интерфейс Executor
- •Интерфейс
- •Thread Pools
- •Thread Pools
- •Executors
- •Пример ExecutorService
- •Пример ExecutorService.invokeAll()
- •InterruptedException
- •Прерывание потока
- •Пример InterruptedException
- •Пример восстановления статуса
- •Пример отменяемой задачи
- •Литература

Совместное использование
ресурсов
21• При многопоточной архитектуре приложения возможны ситуации, когда несколько потоков будут одновременно работать с одними и теми же данными, используя их значения и присваивая новые
•В таком случае результат работы программы становится невозможным предопределить, глядя только на исходный код
•Отсюда следует возможность некорректной работы алгоритма, возникновения исключительных ситуаций
•Решением проблемы является применение механизма блокировки объекта:
Только один поток в один момент времени может установить блокировку на некоторый объект
Попытка блокировки уже заблокированного объекта приводит к останову потока до момента разблокирования этого объекта
Наличие блокировки не запрещает всех остальных действий с объектом
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Совместное использование
ресурсов
22• В Java-программе для того, чтобы воспользоваться механизмом блокировок, существует ключевое
слово synchronized
•Оно может быть применено в двух вариантах – для объявления synchronized-блока и как модификатор метода
•В обоих случаях действие его примерно одинаковое
•Синхронизированный блок:
//Блокируется указанный объект synchronized (ref ) // ref - ссылка на объект
{
// Тело блока синхронизации
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Совместное использование
ресурсов
23• Прежде чем начать выполнять действия, описанные
вэтом блоке, поток обязан установить блокировку на объект, на который ссылается переменная ref
(поэтому она не может быть null)
•Если другой поток уже установил блокировку на этот объект, то выполнение первого потока приостанавливается до тех пор, пока не удастся выполнить блокировку
•После этого блок выполняется
•В случае успешного либо не успешного завершения исполнения, производится снятие блокировки, чтобы освободить объект для других потоков
•Synchronized-методы работают аналогичным образом
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Совместное использование
ресурсов
24• Прежде чем начать выполнять их, поток пытается заблокировать объект, у которого
вызывается метод
•После выполнения блокировка снимается
•Синхронизированный метод:
//Блокируется объект-владелец метода public synchronized void myMethod() {
// Тело метода
}
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Характерные ошибки
25• Отсутствие синхронизации
•Необоснованная длительная блокировка объектов
•Взаимная блокировка
•Возникновение монопольных потоков
•Нерациональное назначение приоритетов
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

volatile
26 Пример 1 curentValue = 5; for(;;){
display.showValue(currentValue);
Thread.sleep(1000);
}
•Если метод showValue() сам по себе не обладает возможностью изменения значения curentValue, компилятор может предположить, что внутри цикла for это значение можно трактовать как неизменное, и использовать одну и ту же константу 5 на каждой итерации цикла при вызове showValue()
•Но если содержимое поля curentValue в ходе выполнения цикла подвержено обновлению посредством других потоков, предположение компилятора окажется неверным
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

volatile
27• Преодолеть проблему может соответствующим способом оформленный синхронизированный код
•Однако существует альтернативный вариант решения проблемы – объявление поля можно снабдить модификатором volatile
•Этот признак свидетельствует о том, что значение поля может быть изменено в любой непредсказуемый момент
•Если объявить curentValue как volatile, компилятор будет вынужден, выполняя каждую итерацию цикла, заново
перечитывать значение переменной
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Специальные методы класса
Object
28• Каждый объект в Java имеет так называемый wait-set, набор потоков исполнения
•Любой поток может вызвать метод wait() любого объекта и таким образом попасть в его wait-set
•При этом выполнение такого потока приостанавливается до тех пор, пока другой поток не вызовет у точно этого же объекта метод notifyAll(), который пробуждает все потоки из wait-set
•Метод notify() пробуждает один, случайно выбранный поток из этого набора
•Однако применение этих методов связано с некоторыми особенностями
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Особенности использования
методов класса Object
29• Метод может быть вызван потоком у объекта только после установления блокировки на этот объект
•Потоки, прежде чем приостановить выполнение после вызова метода wait(), снимают все блокировки
•После вызова освобождающего метода потоки пытаются восстановить ранее снятые блокировки
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |

Прерывание потока
30• public void interrupt() – изменяет статус потока на прерванный
•public static boolean interrupted() –
возвращает и очищает статус потока (прерван или нет)
•public boolean isInterrupted() – возвращает статус потока (прерван или нет)
•В том случае, если в текущий момент поток выполняет методы wait(), sleep(), join(), а его прерывают вызовом метода interrupt(), метод прерывает свое выполнение с выбросом исключения InterruptedException
•Потоку не сообщается, что его прервали
Все права защищены. www.haulmont.ru info@haulmont.com |
© HAULMONT, 2013 |