Скачать презентацию Многопоточность в java Козинов Евгений Содержание Многопоточность Скачать презентацию Многопоточность в java Козинов Евгений Содержание Многопоточность

thread.pptx

  • Количество слайдов: 36

Многопоточность в java Козинов Евгений Многопоточность в java Козинов Евгений

Содержание Многопоточность в java • • • Класс Thread Интерфейс Runnable Работа с приоритетами Содержание Многопоточность в java • • • Класс Thread Интерфейс Runnable Работа с приоритетами Основные возможности синхронизация Методы wait(), notify. All() класса Object Прерывание потоков.

Потоки Поток, в Java представляется экземпляром класса Thread. Для того, чтобы написать свой поток Потоки Поток, в Java представляется экземпляром класса Thread. Для того, чтобы написать свой поток исполнения, необходимо наследоваться от этого класса и переопределить метод • run()

Пример простейшего потока Создание потока public class My. Thread extends Thread { public void Пример простейшего потока Создание потока public class My. Thread extends Thread { public void run() { // некоторое долгое действие, вычисление long sum=0; for (int i=0; i<1000; i++) { sum+=i; } System. out. println(sum); } } Применение потока My. Thread t = new My. Thread(); t. start();

А как еще можно создать поток? Что делать если мы хотим сделать из класса А как еще можно создать поток? Что делать если мы хотим сделать из класса поток и при этом унаследовать его еще от какого-то класса (множественное наследование)? Необходимо реализовать интерфейс Runnable, в котором объявлен метод • void run()

Пример потока через интерфейс Создание потока public class My. Runnable implements Runnable { public Пример потока через интерфейс Создание потока public class My. Runnable implements Runnable { public void run() { // некоторое долгое действие, вычисление long sum=0; for (int i=0; i<1000; i++) { sum+=i; } System. out. println(sum); } } Применение потока Runnable r = new My. Runnable(); Thread t = new Thread(r); t. start();

О Runnable не является полной заменой классу Thread, Создание и запуск самого потока исполнения О Runnable не является полной заменой классу Thread, Создание и запуск самого потока исполнения возможно только через метод Thread. start().

Работа с приоритетами В Java можно назначать потокам приоритеты. • Для этого в классе Работа с приоритетами В Java можно назначать потокам приоритеты. • Для этого в классе Thread существуют методы get. Priority() и set. Priority() Также объявлены три константы: • MIN_PRIORITY • MAX_PRIORITY • NORM_PRIORITY

Пример public class Thread. Test implements Runnable { public void run() { double calc; Пример public class Thread. Test implements Runnable { public void run() { double calc; for (int i=0; i<50000; i++) { calc=Math. sin(i*i); if (i%10000==0) { System. out. println(get. Name()+ " counts " + i/10000); } } } public String get. Name() { return Thread. current. Thread(). get. Name(); } …

Пример … public static void main(String s[]) { // Подготовка потоков Thread t[] = Пример … public static void main(String s[]) { // Подготовка потоков Thread t[] = new Thread[3]; for (int i=0; i

Результат работы Thread 0 started Thread 1 started Thread 2 started Thread 0 counts Результат работы Thread 0 started Thread 1 started Thread 2 started Thread 0 counts 0 Thread 1 counts 0 Thread 2 counts 0 Thread 0 counts 1 Thread 1 counts 1 Thread 2 counts 1 Thread 0 counts 2 Thread 2 counts 2 Thread 1 counts 2 Thread 2 counts 3 Thread 0 counts 3 Thread 1 counts 3 Thread 2 counts 4 Thread 0 counts 4 Thread 1 counts 4

Пример задания приоритетов public static void main(String s[]) { // Подготовка потоков Thread t[] Пример задания приоритетов public static void main(String s[]) { // Подготовка потоков Thread t[] = new Thread[3]; for (int i=0; i

Результат работы Thread 0 started Thread 1 started Thread 2 counts 0 Thread 2 Результат работы Thread 0 started Thread 1 started Thread 2 counts 0 Thread 2 counts 1 Thread 2 counts 2 Thread 2 counts 3 Thread 2 counts 4 Thread 0 counts 0 Thread 1 counts 1 Thread 1 counts 2 Thread 1 counts 3 Thread 1 counts 4 Thread 0 counts 1 Thread 0 counts 2 Thread 0 counts 3 Thread 0 counts 4

Демон-потоки позволяют описывать: • фоновые процессы, которые нужны только для обслуживания основных потоков выполнения Демон-потоки позволяют описывать: • фоновые процессы, которые нужны только для обслуживания основных потоков выполнения • не могут существовать без основных потоков. Для работы с этим «свойством» существуют методы (вызываются до создания потока) • set. Daemon() • is. Daemon(). Процесс всегда дожидается всех потоков не демонов!

Пример public class Thread. Test implements Runnable { // Отдельная группа, в которой будут Пример public class Thread. Test implements Runnable { // Отдельная группа, в которой будут // находиться все потоки Thread. Test public final static Thread. Group GROUP = new Thread. Group("Daemon demo"); // Стартовое значение, // указывается при создании объекта private int start; public Thread. Test(int s) { start = (s%2==0)? s: s+1; new Thread(GROUP, this, "Thread "+ start). start(); } …

Пример … public void run() { // Начинаем обратный отсчет for (int i=start; i>0; Пример … public void run() { // Начинаем обратный отсчет for (int i=start; i>0; i--) { try { Thread. sleep(300); } catch (Interrupted. Exception e) {} // По достижении середины порождаем // новый поток с половинным начальным // значением if (start>2 && i==start/2){ new Thread. Test(i); } } } public static void main(String s[]) { new Thread. Test(16); new Daemon. Demo(); } }

Пример (поток наблюдатель) почему должен быть демоном? public class Daemon. Demo extends Thread { Пример (поток наблюдатель) почему должен быть демоном? public class Daemon. Demo extends Thread { public Daemon. Demo() { super("Daemon demo thread"); set. Daemon(true); start(); } public void run() { Thread threads[]=new Thread[10]; while (true) { // Получаем набор всех потоков из // тестовой группы int count=Thread. Test. GROUP. active. Count(); if (threads. length

Результатом программы Thread 16, Thread 16, Thread 16, Thread 8, Thread 16, Thread 8, Результатом программы Thread 16, Thread 16, Thread 16, Thread 8, Thread 16, Thread 8, Thread 4, Thread 8, Thread 4, Thread 2,

Синхронизация При многопоточной архитектуре приложения возможны ситуации, когда несколько потоков будут одновременно работать с Синхронизация При многопоточной архитектуре приложения возможны ситуации, когда несколько потоков будут одновременно работать с одними и теми же данными (читать и сохранять). В таком случае результат работы программы становится невозможно предугадать. Финальные значения переменных будут зависеть от случайных факторов. Такие программы не могут считаться правильными.

Модификатор volatile При объявлении полей объектов и классов может быть указан модификатор volatile запрещает Модификатор volatile При объявлении полей объектов и классов может быть указан модификатор volatile запрещает КЭШирование данных Зачем это нужно?

Блокировки В Java-программе для того, чтобы воспользоваться механизмом блокировок, существует ключевое слово synchronized. Оно Блокировки В Java-программе для того, чтобы воспользоваться механизмом блокировок, существует ключевое слово synchronized. Оно может быть применено в двух вариантах • synchronized-блока • модификатор метода.

Пример public class Thread. Test implements Runnable { private static Thread. Test shared = Пример public class Thread. Test implements Runnable { private static Thread. Test shared = new Thread. Test(); //Объект общий для всех! public void process() { for (int i=0; i<3; i++) { System. out. println( Thread. current. Thread(). get. Name()+" "+i); Thread. yield(); //отдать управ. } } public void run() { shared. process(); }

Пример public static void main(String s[]) { for (int i=0; i<3; i++) { new Пример public static void main(String s[]) { for (int i=0; i<3; i++) { new Thread( new Thread. Test(), "Thread-"+i). start(); } } }

Результат Thread-0 0 Thread-1 0 Thread-2 0 Thread-0 1 Thread-2 1 Thread-0 2 Thread-1 Результат Thread-0 0 Thread-1 0 Thread-2 0 Thread-0 1 Thread-2 1 Thread-0 2 Thread-1 1 Thread-2 2 Thread-1 2

Пример … public void run() { synchronized (shared) { shared. process(); } } … Пример … public void run() { synchronized (shared) { shared. process(); } } … Результат Thread-0 0 Thread-0 1 Thread-0 2 Thread-1 0 Thread-1 1 Thread-1 2 Thread-2 0 Thread-2 1 Thread-2 2

Synchronized-методы работают аналогичным образом. • Прежде, чем начать выполнять их, поток пытается заблокировать объект, Synchronized-методы работают аналогичным образом. • Прежде, чем начать выполнять их, поток пытается заблокировать объект, у которого вызывается метод. • После выполнения блокировка снимается. В предыдущем примере аналогичной упорядоченности можно было добиться, если использовать не synchronized-блок, а объявить метод process() синхронным.

deadlock При работе с блокировками всегда надо помнить о возможности появления deadlock – взаимных deadlock При работе с блокировками всегда надо помнить о возможности появления deadlock – взаимных блокировок, которые приводят к зависанию программы.

Пример public class Deadlock. Demo { // Два объекта-ресурса public final static Object one=new Пример public class Deadlock. Demo { // Два объекта-ресурса public final static Object one=new Object(), two=new Object(); public static void main(String s[]) { // Создаем два потока, которые будут // конкурировать за доступ к объектам // one и two Thread t 1 = new Thread() { public void run() { // Блокировка первого объекта synchronized(one) { Thread. yield(); // Блокировка второго объекта synchronized (two) { System. out. println("Success!"); } } };

Пример Thread t 2 = new Thread() { public void run() { // Блокировка Пример Thread t 2 = new Thread() { public void run() { // Блокировка второго объекта synchronized(two) { Thread. yield(); // Блокировка первого объекта synchronized (one) { System. out. println("Success!"); } } }; // Запускаем потоки t 1. start(); t 2. start(); } }

Методы wait(), notify. All() класса Object Каждый объект в Java имеет не только блокировку Методы wait(), notify. All() класса Object Каждый объект в Java имеет не только блокировку для synchronized блоков и методов, но и wait-set, набор потоков исполнения. Любой поток может вызвать метод wait() любого объекта и таким образом попасть в его wait-set. • Выполнение потока приостанавливается до тех пор, пока другой поток не вызовет у этого же объекта метод notify. All(). • notify. All() пробуждает все потоки из wait-set. • Метод notify() пробуждает случайный поток. • wait() можно вызвать только синхронно!

Пример public class Wait. Thread implements Runnable { private Object shared; public Wait. Thread(Object Пример public class Wait. Thread implements Runnable { private Object shared; public Wait. Thread(Object o) { shared=o; } public void run() { synchronized (shared) { try { shared. wait(); } catch (Interrupted. Exception e) {} System. out. println("after wait"); } }

Пример public static void main(String s[]) { Object o = new Object(); Wait. Thread Пример public static void main(String s[]) { Object o = new Object(); Wait. Thread w = new Wait. Thread(o); new Thread(w). start(); try { Thread. sleep(100); } catch (Interrupted. Exception e) {} System. out. println("before notify"); synchronized (o) { o. notify. All(); } } }

Ожидание завершения потока Что бы подождать завершение потока необходимо вызвать метод join() • Вызов Ожидание завершения потока Что бы подождать завершение потока необходимо вызвать метод join() • Вызов блокирующий! В методе можно указать время ожидания

Прерывание потока Для прерывания потока применяют исключения. Вызываются исключения методом interrupt() Проверить прерван ли Прерывание потока Для прерывания потока применяют исключения. Вызываются исключения методом interrupt() Проверить прерван ли поток можно по средствам is. Interrupted() или interrupted() Последний сбрасывает флаг и может быть вызван только из потока!

Полезные методы boolean is. Alive() – поток жив? set. Name(String thread. Name) – задает Полезные методы boolean is. Alive() – поток жив? set. Name(String thread. Name) – задает имя потока. String get. Name() – получает имя потока. static Thread. current. Thread() – статический метод, возвращающий объект потока, в котором он был вызван. long get. Id()– возвращает идентификатор потока. Идентификатор – уникальное число, присвоенное потоку.

Вопросы? Вопросы?