2010-06-16 23 views
5

Mam klasę, która rozszerza klasę Thread i ma swoją metodę uruchamiania zaimplementowaną w ten sposób.Zarządzanie wątkami android onPause

public void run(){ 
    while(!terminate){ 
     if(paused){ 
      Thread.yield(); 
     }else{ 
      accummulator++; 
     } 
    } 
} 

Ten wątek jest spawnowany z metody onCreate.

Kiedy mój interfejs użytkownika jest ukryty (po naciśnięciu klawisza Home), moja metoda onPause ustawi wstrzymaną flagę na true i ustąpi bieżnika. Jednak w DDMS wciąż widzę czas utylizacji wątku i jego stan jako "działający".

Moje pytanie brzmi. Jaki jest właściwy sposób zatrzymania wątku, aby nie zużywał on czasu procesora?

Odpowiedz

4

To jest naprawdę zła praktyka, aby utrzymywać wątek działający po onPause. Powodem jest to, że po onPause Twoja aplikacja może w każdej chwili zniknąć z pamięci bez twojej wiedzy, dlatego nie będziesz mógł posprzątać po sobie.

Właściwym sposobem na to jest zatrzymanie wątku w trybie Wstrzymaj i ponownie utwórz go w trybie odtwarzania. Jeśli potrzebujesz stanu, możesz użyć wbudowanych w Android metody saveState lub ustawień, lub cokolwiek, aby to zachować.

+0

Tak, to także wniosek, który wymyśliłem. Dodatkowo uważam, że najlepszą metodą implementacji nie jest podklasy bezpośrednio z wątku, ale użycie interfejsu Runnable. W ten sposób możesz zabić wątek, ale wciąż masz możliwość "wznowienia" go przez utworzenie kolejnego wątku, bez utraty stanu. Przyznano, że onDestroy lub aplikacja nie zostanie zabita i odtworzona. –

0

Twoja zmienna paused najprawdopodobniej jest buforowana lokalnie. Dzieje się tak dlatego, że jest tylko czytany i nie jest zmieniany w pętli. Tak więc dzieje się tak, że kompilator/interpreter/jitter optymalizuje się, odczytując tylko zmienną raz, a następnie wykonując tylko gałąź else. Musisz oznaczyć to pole jako volatile dla zmiennej pause, aby odczytać każdą iterację przez pętlę. Zapoznaj się z documentation słowa kluczowego . Oto some info about threading i some info about synchronization and concurrency.

+0

Nie martwię się zbytnio o wstrzymaną zmienną zajmującą zasoby. Obawiałem się, że wątek nadal się zapętla, mimo że wątek interfejsu użytkownika został zatrzymany. –

+0

Zaktualizowałem odpowiedź, aby dokładniej wyjaśnić, co się dzieje. Odpowiedź nie dotyczyła zmiennej pauzy i zasobów. Wątek nadal się zapętla, ponieważ wstrzymana zmienna nie jest oznaczona jako niestabilna i nie jest ponownie czytana. To tylko jedna z subtelności programowania wielowątkowego. – Qberticus

1

Mimo że wywołujemy thread.yield(), znajdujemy się w pętli while(), która prawdopodobnie zapętla się tysiące razy na sekundę, za każdym razem wywołując .yield(), ale fakt, że zapętla się kontroli oznacza, że ​​zużywa zasoby. Jeśli umieścisz tam wiadomość Log.d, zobaczysz, co mam na myśli.

Polecam używanie Thread.sleep() zamiast Thread.yield(). Powodem jest, że podczas gdy wątek śpi, ustąpi. Dodatkowo dzięki usypianiu zyskujesz dodatkową korzyść spowolnienia pracy urządzenia i nie zużywasz zasobów. Interwał snu równy 500 ms powinien wystarczyć =)

+0

wątek zostanie ostatecznie użyty jako wątek renderowania na płótnie i powinien zostać wykonany tak szybko, jak to możliwe. Myślę, że zamierzam spróbować zabić wątek i odtworzyć go w lokalnym programie obsługi –

+0

Wystarczająco fair. Warto podkreślić, że zamknięte pętle, takie jak te w kodzie, to procesory wieprzowe. Na urządzeniu mobilnym wiedźma cpu szybko się rozładuje. –

+0

Nie miałem problemu z 'Thread.yield' (alias' Thread.sleep (0) ') i wysokim wykorzystaniem procesora - program do planowania wątków ma minimalną ziarnistość * znacznie poniżej *" tysiące razy na sekundę ". –

Powiązane problemy