Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
java all-in-one.docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
1.97 Mб
Скачать

Барьеры

Барьер это средство синхронизации, которое используется для того, чтобы некоторое множество потоков ожидало окончания друг друга в некотором месте, являющемся барьером или точкой синхронизации. После того, как все потоки достигли точки синхронизации, они разблокируются и могут продолжать выполнение. На практике барьеры используются для сбора результатов выполнения некоторой распараллеленной задачи. В качестве примера можно рассмотреть задачу умножения матриц. При распараллеливании данной задачи каждому потоку будет поручено умножения определенных строк на определенные столбцы. В точке синхронизации же полученные результаты собираются из всех потоков, и строится результирующая матрица. В пакете java.util.concurrent класс CyclicBarrier является реализацией барьера. 

Затвор

Затвор – средство синхронизации, которое используются для того, чтобы один или несколько потоков могли дождаться выполнения определенного числа операции в других потоках. Класс CountDownLatch пакета java.util.concurrent является средством синхронизации, обладающим вышеперечисленными свойствами. Данный класс работает по принципу таймера. Происходит инициализация его некоторым начальным значением и обратный отсчет. При вызове метода await данного класса каким-либо потоком, он переходит в состояние ожидания момента достижения счетчиком таймера значения 0. На практике данный класс удобно использовать для координации момента начала и окончания определенного числа потоков. Это означает следующее:

  • можно сделать так, чтобы определенное число потоков начиналось в один и тот же момент времени;

  • можно отследить момент окончания нескольких потоков.

28. Расширенные методы синхронизации. Блокировка чтения и записи, Exchanger. Многопоточные приложения и Swing.

Условия: Имеются общие данные, к которым потоки обращаются на чтение и изменение (запись). При этом изменение данных происходит относительно редко. Гораздо чаще происходит их чтение.  Несколько потоков, которые читают данные, не изменяя их, не создают проблем друг другу. Поэтому нет смысла их синхронизировать - ведь они не мешают друг другу. Но если хотя бы один поток начал изменение данных, то все другие потоки (читающие и изменяющие данные) должны подождать, пока этот поток не закончит работу. Т.е. мы можем иметь множественных одновременных читателей данных, но лишь один поток, который меняет данные.  Задача: Требуется эффективно синхронизировать читающие и изменяющие потоки между собой.  Решение: Для начала, еще раз подытожим условия блокировки: Доступ для чтения: если нет потоков, которые изменяют данные, а также нет потоков, которые запросили доступ для изменения данных. Доступ для записи: если нет потоков, которые читают или изменяют данные. Если поток хочет прочитать данные, то это позволяется, если ни один поток не изменяет данные и ни один поток не запросил доступ на запись данных. Мы отдаем записи данных более высокий приоритет, чем чтению. Если бы мы так не делали, то могло бы возникнуть "голодание" (starvation) потоков, изменяющих данные (при условии, что запросы на чтение данных происходят чаще, чем запросы на запись данных). Потоки, запрашивающие доступ на запись, должны были бы ждать, пока не отработают потоки, читающие данные. Так как запросов на чтение много, то новые читающие потоки добавлялись бы постоянно, что привело бы в долговременному (а то и вообще бесконечному) простою потоков на запись. Поэтому поток может получить разрешение на чтение, только если ни один поток не изменяет данные и ни один поток не запросил доступ на запись.  Поток, который хочет получить доступ к записи данных, получает этот доступ, если только ни один поток не читает и не пишет данные. Приэтом не имеет значения, сколько поток запросило доступ на запись, так как мы хотим обеспечить равные шансы всем этим потокам. 

public class Exchanger<V>

extends Object

Точка синхронизации, в которой потоки могут соединить и подкачать элементы в пределах пар. Каждый поток представляет некоторый объект на записи в exchange метод, соответствует с потоком партнера, и получает объект своего партнера по возврату. Теплообменник может быть просмотрен как двунаправленная форма a SynchronousQueue. Теплообменники могут быть полезными в приложениях, таких как генетические алгоритмы и конвейерно обработать проекты. Организация потоков в среде Java* позволяет добиться прироста производительности практически во всех приложениях. Узнайте, как многопоточность становится стандартным средством программирования в среде Java*, благодаря технологии Hyper-Threading и возможностям новых многоядерных процессоров Intel.

При запуске любой программы образуется, по крайней мере, один поток. В С/С++ и Java этот поток запускается при вызове метода main(). Для создания дополнительных потоков необходимо их запустить и назначить им определенные функции, после выполнения которых потоки автоматически будут завершены виртуальной машиной. В среде Java для создания потока и назначения им функций есть два способа. Первым из них является наследование от класса Thread (входящего в пакет java.lang) с последующим переопределением метода run() на функцию, которую вы хотите назначить для потока.

Swing

 Swing ― это старый инструментарий, разработанный задолго до появления красивых пользовательских интерфейсов, и некоторые компоненты, которые могут потребоваться для создания многофункциональных UI, в нем отсутствуют. К счастью, такие проекты по разработке ПО с открытым исходным кодом, как Substance, SwingX и Java™ Look-and-Feel Graphics Repository, меняют это положение.  С ростом сложности приложений они неизбежно требуют более гладкой работы множества потоков. Но это прямое противоречие дизайну Swing API. Чтобы обойти это несоответствие, компания Sun определила несколько методов в AWT и Swing API, чтобы дать разработчикам возможность использовать множественные потоки в этой однопоточной модели, которая стоит в основе дизайна Swing API. Основная идея заключается в том, чтобы разместить все инструкции, касающиеся GUI, в потоке событий. Чтобы сделать это, необходимо поставить их в очередь событий. Следующие два метода доступны как статические методы классов javax.swing.SwingUtilities и java.awt.EventQueue: . invokeLater(Runnable r) вызывает метод r.run() для выполнения событий AWT асинхронно с потоком. Этот поток будет обработка, как только он достигнет вершины очереди событий.

. invokeAndWait(Runnable r) заставляет вызывать метод r.run() одновременно с потоком выполнения событий AWT.

InvocationTargetException – это исключение-обертка, которое будет выброшено, если наш Runnable-объект выбросит какое-нибудь другое исключение. Фактически выброшенное Runnable-объектом исключение будет содержаться внутри InvocationTargetException. Используя эти два метода, многопоточное приложение вполне может как синхронно, так и асинхронно взаимодействовать с очередью событий и таким образом твердо следовать принципу одиночного потока Swing API.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]