Компромисс с объявлением метода синхронизированы в Java? - PullRequest
5 голосов
/ 27 июля 2011

У меня была проблема с блокировкой потока по какой-то еще неизвестной причине в моем приложении для Android, когда я пытался убить поток B из потока A (обычно, иногда это работало).Я догадался, что это потому, что некоторые из моих методов делали вызовы между потоками без синхронизации.Я сделал метод cancel и множество методов, которые по существу синхронизировали обработчики событий и сделали несколько общих переменных нестабильными, и все работало.

Я не знаю, какие из 20 нечетных объявлений volatile / synchronized я добавил на самом делерешил проблему, и это заставило меня задуматься: «Должен ли я заботиться? Это работает, не связывайтесь с этим!»

Итак, мой вопрос: Есть ли компромисс, связанный с объявлением метода синхронизированным?или примитивно изменчивый?Есть ли какая-либо причина избегать этих объявлений, если они не нужны?

Редактировать
Рассматриваемый поток (ы) - это соединение Bluetooth, которое получает / отправляет потоковую передачуданные, поэтому ASyncTask и другие решения типа рабочих потоков не работают хорошо.Они предназначены для выполнения конечной задачи и завершения по окончании.Некоторые, такие как ASyncTask, также добавляют много накладных расходов, которые просто убивают приложение.Для непрерывно работающих потоков, подобных этому, использование Thread по-прежнему является лучшим способом сделать это.

Я использую Android Сервис для создания и управления потоками, поэтому я следую парадигмам дизайна Android в этом отношении.

Ответы [ 2 ]

4 голосов
/ 27 июля 2011

По моему опыту, как правило, проще и часто более эффективно выполнять блокировку на как можно более детальном уровне, используя синхронизированный (объект) {...} для доступа к определенному объекту.Кроме того, если есть несколько блокировок, которые вы должны получить одновременно, ВСЕГДА убедитесь, что вы всегда получаете их в одном и том же порядке.

Статические методы имеют свой собственный кусок странности, о котором нужно беспокоиться;метод синхронизированного экземпляра будет синхронизироваться только с этим экземпляром, а не с классом в целом, поэтому, если вам нужно синхронизировать оба метода в методе экземпляра, вам нужно будет выполнить что-то вроде synchronized (this.class) {...} также, хотя, если вы применяете вышеупомянутое, на самом деле вы просто выполняете synchronized () над статическими полями, к которым вы обращаетесь в конкретном методе.

Как еще одно примечание, в целомвы не хотите создавать свои собственные потоки, а вместо этого должны использовать уже существующие в системе механизмы управления потоками (такие как ThreadPoolExecutor для текущих очередей работы или AsyncTask для асинхронных обновлений пользовательского интерфейса).ThreadPoolExecutor имеет тенденцию быть более производительным (и может лучше использовать многоядерные устройства), но вам придется проделать дополнительную работу, если он собирается что-то делать с пользовательским интерфейсом;AsyncTask, с другой стороны, имеет тенденцию быть немного медленнее и тяжелее, но он также выполняет свой обратный вызов onPostExecute в потоке пользовательского интерфейса.

0 голосов
/ 27 июля 2011

Если это работает, не исправляйте это сейчас :), но для следующего проекта вы должны рассмотреть возможность использования AsyncTask . Dev Guide . Я не думаю, что влияние на производительность не имеет реального значения в контексте Android, но сложность, удобочитаемость и возможность сопровождения в будущем могут быть проблемой (отмена / уничтожение потока, много общих переменных).

...