Устраняет ли класс android.os.Handler необходимость объявления определенных методов синхронизированными? - PullRequest
4 голосов
/ 04 марта 2011

Собирая простое приложение «Часы», я обнаружил, что Android требует от вас использования android.os.Handler, который находится в потоке A, чтобы обновить объекты View в потоке A, используя результаты данных, полученных из потока B.

Я все еще относительно новичок в Java, и это первый раз, когда я раньше имел дело с потоками, но я знаю, что обычно вы объявляете методы и / или операции как синхронизированные, если два разных потока хотят получить доступ одни и те же данные. Тем не менее, кажется, что android.os.Handler является специфичным для Android способом синхронизации данных между потоками, так что вы избегаете classic ошибок параллелизма , подробно описанных в документации Oracle, с которой я только что связался , Это правда?

Если бы я оказался в такой ситуации, что ОС Android потребовала для использования android.os.Handler для передачи данных из одного потока в другой, значит ли это, что я не должны объявить методы, используемые для получения этих данных, как синхронизированные?

Ответы [ 3 ]

11 голосов
/ 04 марта 2011

Мое понимание:

A Обработчик - это всего лишь механизм доставки информации между двумя потоками.Это не единственный механизм, но это механизм, который Google выбрал для добавления простых методов в Activity для выполнения общих задач.

Из документа

Когда процессСозданный для вашего приложения, его основной поток предназначен для запуска очереди сообщений, которая заботится об управлении объектами приложений верхнего уровня (действиями, широковещательными приемниками и т. д.) и любыми окнами, которые они создают.Вы можете создавать свои собственные потоки и общаться с основным потоком приложения через обработчик.Это делается путем вызова тех же методов post или sendMessage, что и раньше, но из новой темы.Затем данный Runnable или Message будет запланирован в очереди сообщений обработчика и обработан при необходимости.

Основной поток выполняет обработчик.Обработчик отвечает за выполнение ваших действий и управление средой приложения.Обработчик - это просто цикл сообщений, который отправляет вещи из MessageQueue.Вот почему ваш поток должен запускать Looper , чтобы создать обработчик.Чтобы синхронизировать другие вещи, которые вы хотите сделать с этим усилием, вы должны вставить свои запросы в эту очередь сообщений, чтобы основной поток приложения выполнял вашу работу.Интерфейс пользователя написан так, что пока только один поток получает доступ к объектам, он функционирует.

Полагаю, смысл этого заключался в том, чтобы указать, что обработчик является одним из механизмов для выполнения синхронизации.Конечно, внутренняя часть MessageQueue написана для учета синхронизации, хотя это грубое упрощение, чтобы сказать «если несколько потоков обращаются к ней, она должна быть синхронизирована».Хотя пользовательский интерфейс является наиболее частым примером, использование Handler и Looper - это просто механизм для разработки многопоточного приложения, которое обеспечивает однопоточную синхронизацию для обработки событий.

Нужно или нет синхронизироватьвы отправляете обработчику в значительной степени зависит от того, что вы отправляете.Если вы говорите о синхронизации вызовов с вещами post, то нет, обработчик позаботится об этом.Если вы говорите о коде внутри Runnable, который вы публикуете в обработчике, поймите, что единственная гарантия обработчика - то, что ваш исполняемый файл будет выполняться с использованием потока, создавшего обработчик.Вам нужно будет продолжать обеспечивать синхронизацию с другими ресурсами.

3 голосов
/ 04 марта 2011

Вам когда-либо понадобится synchronized, только если у вас есть общий ресурс, например ArrayList или что-то, что может быть прочитано из двух потоков одновременно.

Сам по себе обработчик не мешаетлюбой параллелизм просто упрощает выполнение вещей, которые должны происходить в потоке пользовательского интерфейса, даже если рабочий поток пытается их выполнить.

Чтобы ответить на ваш вопрос: если вы используете обработчик, онобычно означает, что вы делаете определенные критические вещи в потоке пользовательского интерфейса.Например, у вас есть ArrayList, который вы инициализируете в onCreate, а затем, возможно, обновляете в обработчике щелчков или что-то в этом роде.Теперь, если вы используете Обработчик, чтобы изменить это, тогда ВСЕ доступ к ArrayList будет происходить в потоке пользовательского интерфейса, поэтому нет необходимости в synchronized.

Однако, как только вы получите доступ к этому ArrayList изнутрирабочий поток, вам нужно будет синхронизировать каждый доступ к нему.

0 голосов
/ 14 февраля 2013

Synchronized, wait и notify являются низкоуровневыми конструкциями параллелизма, поверх которых реализованы высокоуровневые конструкции параллелизма, такие как семафоры, блокирующие очереди, барьеры и Looper / Handler.

Большая часть того, что вы видите в java.util.concurrent (который реализует шаблоны / конструкции параллелизма высокого уровня), реализована поверх синхронизированных, ожидающих и уведомляющих (если вы игнорируете алгоритмы без блокировки)

Механизм Looper / Handler в основном упрощенная реализация шаблона «производитель-потребитель», когда у вас есть один потребитель, но несколько производителей. Он был создан для простого обмена сообщениями между потоками пользовательского интерфейса и потоками, не относящимися к пользовательскому интерфейсу. Поток пользовательского интерфейса в Android работает как однопотоковый цикл (т. Е. Один потребитель), но может принимать обновления от нескольких потоков, не относящихся к пользовательскому интерфейсу (т. Е. От нескольких производителей через обработчики).

...