2010-06-16 6 views
5

J'ai une classe qui étend la classe Thread et dont la méthode d'exécution est implémentée.android gestion des threads onPause

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

Ce thread est issu de la méthode onCreate.

Lorsque mon interface utilisateur est masquée (lorsque la touche Accueil est enfoncée), ma méthode onPause met l'indicateur en pause à true et génère la bande de roulement. Cependant, dans le DDMS, je vois encore le temps d'accumulation du thread et son état "en cours d'exécution".

Donc ma question est. Quelle est la bonne façon d'arrêter le thread afin qu'il n'utilise pas le temps CPU?

Répondre

4

Il est en fait mauvais de garder un thread en cours d'exécution après onPause. La raison en est que, après une pause, votre application peut tomber à court de mémoire à tout moment sans que vous puissiez savoir, donc vous ne serez pas en mesure de nettoyer après vous.

La meilleure façon de le faire est d'arrêter le thread onPause et de le recréer dans OnResume. Si vous avez besoin d'un état, vous pouvez utiliser les méthodes ou paramètres saveState d'Android, ou ceux qui vous permettent de le conserver.

+0

Oui, c'est la conclusion que j'ai trouvée. En outre, je pense que la meilleure méthode de mise en œuvre n'est pas de sous-classer directement Thread mais d'utiliser l'interface Runnable. De cette façon, vous pouvez tuer le thread mais avoir la possibilité de le "reprendre" en instanciant un autre thread, sans perdre d'état. Accordé que onDestroy ou l'application n'est pas tué et recréé. –

0

Votre variable paused est très probablement mise en cache localement. C'est parce que c'est seulement lu et pas changé dans la boucle. Donc, ce qui se passe est que le compilateur/interpréteur/gigue optimise en lisant la variable une seule fois et en n'exécutant que la branche else. Vous devez marquer ce champ comme volatile pour que la variable pause soit lue à chaque itération de la boucle. Découvrez le mot-clé documentation du mot-clé volatile. Voici some info about threading et some info about synchronization and concurrency.

+0

Je ne m'inquiète pas autant des ressources occupées variables en pause. Je m'inquiétais que le thread soit toujours en boucle même si le thread de l'interface utilisateur s'est arrêté. –

+0

J'ai mis à jour la réponse pour expliquer plus clairement ce qui se passe. La réponse ne concernait pas la variable de pause et les ressources. Le thread est toujours en boucle car la variable en pause n'est pas marquée comme volatile et n'est pas relue. Ce n'est qu'une des subtilités de la programmation multi-thread. – Qberticus

1

Même si vous appelez thread.yield(), vous êtes à l'intérieur d'une boucle while() qui boucle probablement des milliers de fois par seconde, à chaque fois que vous appelez .yield() mais le fait qu'il soit en boucle de contrôle signifie qu'il utilise des ressources. Si vous y mettez un message Log.d, vous verrez ce que je veux dire. Je recommande d'utiliser un Thread.sleep() au lieu de Thread.yield(). La raison étant, pendant qu'un fil dort, il est cédé. De plus, avec le sommeil, vous avez l'avantage de ralentir le while() et de ne pas utiliser de ressources. Un intervalle de veille de 500 ms devrait être suffisant =)

+0

le thread sera finalement utilisé comme un thread de rendu sur un canevas et il devrait s'exécuter aussi vite que possible. Je pense que je vais essayer de tuer le fil et le recréer dans le gestionnaire onresume –

+0

Assez juste. Il est important de souligner que les boucles fermées comme celle de votre code sont des processeurs de CPU. Sur un appareil mobile, un cpu hog mange la batterie rapidement. –

+0

Je n'ai pas eu de problème avec 'Thread.yield' (aka' Thread.sleep (0) ') et une utilisation élevée du processeur - le planificateur de threads a une granularité minimale * bien en dessous de *" milliers de fois par seconde ". –

Questions connexes