2011-07-27 13 views
5

Miałem problem z zablokowaniem wątku z nieznanego powodu w mojej aplikacji na Androida, gdy próbowałem zabić wątek B z wątku A (zazwyczaj czasami zadziałało). Podejrzewałem, że to dlatego, że niektóre z moich metod nawiązywały połączenia przez wątki bez synchronizacji. Zrobiłem metodę anulowania i wiele metod, które były zasadniczo procedurami obsługi zdarzeń zsynchronizowane i uczyniły kilka wspólnych zmiennych zmiennymi i wszystko działało.Zwalczaj z deklarowaniem metody synchronizowanej w java?

Nie wiem, który z 20 dziwnych lotnych/zsynchronizowanych deklaracji, które dodałem, faktycznie rozwiązał problem, a to spowodowało, że pomyślałem: "Czy powinienem się przejmować? To działa nie zadzieraj!"

Moje pytanie brzmi: Czy istnieje jakikolwiek kompromis związany z deklarowaniem metody zsynchronizowanej lub prymitywnej? Czy jest jakiś powód, aby unikać tych deklaracji, jeśli nie są one potrzebne?

Edit
Gwint (y) w pytaniu jest połączenie Bluetooth, które odbiera/wysyła dane strumieniowe, więc ASyncTask i inne rozwiązania typu gwintu pracownik nie działają dobrze. Są one zaprojektowane do wykonywania zadań skończonych i kończenia po zakończeniu. Niektóre, takie jak ASyncTask, również dodają wiele kosztów, które po prostu zabijają aplikację. W przypadku nieprzerwanych wątków takich jak ten, używanie wątku jest nadal najlepszym sposobem na zrobienie tego.

Używam Androida Service do generowania wątków i zarządzania nimi, więc podążam za wzorami projektowymi Androida pod tym względem.

+0

Istnieje (mała?) Nieodłączna kara za wydajność. Trudno powiedzieć, jaki był "problem z blokowaniem wątku" (odpytywanie nieulotnego pola składowego?), Ale dobrowolne dodanie "zsynchronizowanego" brzmi jak dobry sposób na uzyskanie impasu i skąd wiadomo, że twoja aplikacja jest wolny od warunków wyścigu?Największym problemem jest to, że masz * dużo * współdzielonego stanu między wątkami - musisz zdecydować, co należy udostępnić, upewnić się, że współdzielony stan jest bezpieczny dla wątków (w jak największym stopniu niezmienny pomaga) i zdecydować, w jaki sposób komunikować się z wątkami (Handler/ConcurrentLinkedQueue/LinkedBlockingQueue?). –

Odpowiedz

-1

Jeśli to działa, nie naprawiaj tego na razie :), ale dla następnego projektu powinieneś rozważyć użycie AsyncTask. Dev Guide. Nie sądzę, aby wpływ na wydajność nie był poważny w kontekście Androida, ale złożoność, czytelność i możliwość późniejszej konserwacji mogą stanowić problem (anuluj/zabij wątek, wiele wspólnych zmiennych).

+0

Wiem o ASyncTask, ale jest to aplikacja komunikacji Bluetooth, która wymaga stale działającego wątku. ASyncTask jest przeznaczony dla jednego zadania, które zakończy się w skończonym czasie w przyszłości, a nie stabilnym połączeniem. ASyncTask jest świetny, ale to nie jest magiczna kula. – CodeFusionMobile

+0

Niestety, nie wiedziałem, gdzie go używać, ale w oparciu o "20 nieparzystych lotnych/zsynchronizowanych" jest nadal dość skomplikowane dla programu Java. – user802421

+2

W przypadku komunikacji Bluetooth w tle, czy nie powinieneś robić tego zamiast ciągłej usługi? Pozwól systemowi Android zarządzać wątkiem usługi i poproś aplikację o rozmowę z usługą. – fluffy

4

Z mojego doświadczenia wynika, że ​​łatwiejsze i często bardziej wydajne jest wykonywanie blokowania w możliwie najdokładniejszym poziomie, z wykorzystaniem zsynchronizowanego (obiektu) {...} dostępu do określonego obiektu. Ponadto, jeśli istnieje kilka zamków, które musisz nabyć w tym samym czasie, ZAWSZE upewnij się, że zawsze je kupujesz w tej samej kolejności.

Metody statyczne mają swój własny dziwaczny niepokój; Zsynchronizowana metoda instancji będzie zsynchronizowana tylko z tą instancją, a nie z klasą jako całością, więc jeśli chcesz zsynchronizować obie metody instancji, musisz wykonać synchronizację (this.class) {.. .}, ale jeśli zastosujesz powyższe, naprawdę po prostu robisz synchronizację() nad statycznymi polami, do których wchodzisz w konkretnej metodzie.

Jako kolejna uwaga, na ogół nie chcesz tworzyć własnych wątków, a zamiast tego należy używać wcześniej istniejących mechanizmów zarządzania wątkami (takich jak ThreadPoolExecutor dla bieżących kolejek roboczych lub AsyncTask dla asynchronicznych aktualizacji interfejsu użytkownika) . ThreadPoolExecutor wydaje się być bardziej wydajny (i może lepiej wykorzystywać urządzenia wielordzeniowe), ale musisz wykonać dodatkową pracę, jeśli zamierzasz coś zrobić z interfejsem; Z drugiej strony, AsyncTask ma tendencję do bycia nieco wolniejszym i cięższym, ale uruchamia również wywołanie zwrotne onPostExecute w wątku UI.

+0

Wszystkie te metody (ThreadPool, ASyncTask, itp.) Są zaprojektowane do uruchamiania zadania lub jakiejś formy intensywnego przetwarzania, które zakończy się po zakończeniu pracy. Zarządzam aktywnym połączeniem bluetooth i wysyłam dziesiątki różnych pakietów danych oraz monitoruję wiele stanów połączeń i zmiennych. W przypadku niezakończonego procesu takiego jak AsyncTask i wątki robocze nie są właściwym wyborem. – CodeFusionMobile

+0

OK. Mój trzeci akapit był bardziej ogólną regułą i nie dotyczył twojego pytania jako edytowanego, ale wciąż należy o tym pamiętać. – fluffy

Powiązane problemy