IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Un thread énergivore


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut Un thread énergivore
    Bonjour à toutes et à tous,

    Je code une application GPS se servant d'un GPS blueTooth externe. Tout fonctionne très bien, sauf que mon appli me vide la batterie à la vitesse grand V (j'ai réussi à coincer un ampèremètre entre la batterie et le smartphone pour le vérifier).

    J'y ai mis du temps, mais j'ai réussi à voir d'où vient le problème. Le thread qui lit les informations en provenance du GPS tourne en permanence : boucle while(true). Avec un petit compteur (tc), j'ai pu vérifier que cette boucle est parcourue environ 80000 fois par seconde ... une à deux fois me suffisent.

    Comment résoudre ce problème ? A mon sens, il faudrait lancer ce thread quelques fois par secondes, mais comment ?

    Je suppose que vous avez des idées.

    Merci de votre aide.

    Pierre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    	private class ReceiverThread extends Thread {
    		Handler handler;
    		ReceiverThread(Handler h) {
    			handler = h;
    		}
    		@Override public void run() {
    			while(true) {
    				tc = tc+1;
    				try {
    					if(receiveStream.available() > 0) {
    						byte buffer[] = new byte[100];
    						int k = receiveStream.read(buffer, 0, 100);
    						if(k > 0) {
    							byte rawdata[] = new byte[k];
    							for(int i=0;i<k;i++)
    								rawdata[i] = buffer[i];							
    							String data = new String(rawdata);
    							Message msg = handler.obtainMessage();
    							Bundle b = new Bundle();
    							b.putString("receivedData", data);
    			                msg.setData(b);
    			                handler.sendMessage(msg);
    						}
    					}
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}

  2. #2
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut
    en java traditionnel, on ajoute un "sleep" dans le Thread:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                try {
                    sleep(500); // attente d'une 1/2 seconde
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
    je suppose que cela existe pour android

    ce qui donnerait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    	private class ReceiverThread extends Thread {
    		Handler handler;
    		ReceiverThread(Handler h) {
    			handler = h;
    		}
    		@Override public void run() {
    			while(true) {
    				tc = tc+1;
    				try {
    					if(receiveStream.available() > 0) {
    						byte buffer[] = new byte[100];
    						int k = receiveStream.read(buffer, 0, 100);
    						if(k > 0) {
    							byte rawdata[] = new byte[k];
    							for(int i=0;i<k;i++)
    								rawdata[i] = buffer[i];							
    							String data = new String(rawdata);
    							Message msg = handler.obtainMessage();
    							Bundle b = new Bundle();
    							b.putString("receivedData", data);
    			                msg.setData(b);
    			                handler.sendMessage(msg);
    						}
    					}
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    
                                     try {
                                          sleep(500); // attente d'une 1/2 seconde
                                      } catch (InterruptedException ex) {
                                          ex.printStackTrace();
                                      }
    			}
    		}
    	}
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Népomucène Voir le message
    en java traditionnel, on ajoute un "sleep" dans le Thread:
    Oui c'est bien ce qu'il faut pour faire et pause, et empêcher une attente active de bouffer tout le CPU comme c'est le cas...


    Mais désolé ce n'est pas vraiment une belle solution dans ce cas là, car pour moi le problème vient de l'utilisation d'available() qui est totalement inutile et contre-productif !
    On a une boucle d'I/O non-bloquante avec available()... et maintenant on voudrais la rendre bloquante avec des sleep().

    Autant lire directement l'InputStream, ce sera bloquant sans rien bricoler.

    available() est inutile dans la grande majorité des cas (tout comme Reader.ready() au passage).
    Pire il peut même être la source d'erreur ou de problème (comme ici).
    En plus de 10 ans d'expérience Java et à fréquenter les forums de DVP je n'ai jamais vu une utilisation d'available() qui soit utile/correcte.



    Au passage il est préférable de sortir le "buffer" de la boucle (pour éviter de le recréer à chaque fois), et le "rawdata" est inutile puisqu'on a un constructeur de String adapté...
    Quand au e.printStackTrace() pour gérer l'exception c'est pas tip-top. Si on ne sait pas quoi faire autant l'englober dans une RuntimeException.

    Bref pour moi cela donnerait quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    	@Override
    	public void run() {
    		try {
    			byte buffer[] = new byte[100];
    			int k;
    			while ((k = receiveStream.read(buffer, 0, 100)) > 0) {
    				String data = new String(buffer, 0, k);
    				Message msg = handler.obtainMessage();
    				Bundle b = new Bundle();
    				b.putString("receivedData", data);
    				msg.setData(b);
    				handler.sendMessage(msg);
    			}
    		} catch (IOException e) {
    			throw new RuntimeException(e);
    		}
    	}

    Et le thread sera mis en sommeil tant qu'il n'y a aucune donnée à lire...


    a++

  4. #4
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    J'avais d'emblée, sans l'avoir même essayée écarté cette solution car je m'étais dit que le sleep(xxx) n'était qu'une boucle bouffe temps. C'est vrai, à la grosse différence près qu'elle ne consomme rien .

    Donc, un grand merci à toi Népomucène de m'avoir remis sur les rails.

    Mon appli sans sleep() consomme 0.5 A.

    Elle ne consomme plus que 0.2 A avec ; c'est-à-dire à peu près la même chose que lorsque je n'exécute pas le thread.

    Cordialement.

    Pierre

  5. #5
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut
    @ChPr je pense qu'il faut que tu creuses aussi l'analyse d'adiGuba (beau travail )
    pour faire un code "bien propre" et à nouveau mesurer la consommation.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Népomucène Voir le message
    @ChPr je pense qu'il faut que tu creuses aussi l'analyse d'adiGuba (beau travail )
    pour faire un code "bien propre" et à nouveau mesurer la consommation.
    La différence de consommation sera identique ou presque.
    Le sleep() corrige cela en faisant passer le traitement de 80000 itérations par secondes à 2 itérations seulement.


    C'est juste que c'est se compliquer la vie pour rien, et que la manière directe est à la fois plus simple et plus efficace.


    a++

  7. #7
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    adiGuba, j'ai mis en œuvre ta solution : ça fonctionne très bien. cependant quelques questions.
    lorsque je me déconnecte, le throw new RuntimeException(e); me fait planter mon application, je l'ai remplacé par ne rien faire : ça marche.

    Je n'ai pas bien compris le fonctionnement de ton thread. Dans celui du départ, grâce à la boucle while(true), on ne sortait jamais du thread ; c'est ce qui en causait la grosse consommation. Dans ce que tu proposes, si k <= 0 on sort de la boucle. Je n'ai pas pu le vérifier, mais alors, que se passe-t-il ? qui relance le thread ?

    Question annexe : mon message fait entre quelques caractères et environ 500 caractères. Quelle est la taille la mieux adaptée à prendre pour le buffer ?

    Cordialement.

    Pierre

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  2. récupérer la valeur de sortie d'un thread
    Par jakouz dans le forum Langage
    Réponses: 3
    Dernier message: 31/07/2002, 11h28
  3. Programmer des threads
    Par haypo dans le forum C
    Réponses: 6
    Dernier message: 02/07/2002, 13h53
  4. Réponses: 5
    Dernier message: 12/06/2002, 15h12
  5. [Kylix] Pb de Thread !!
    Par Anonymous dans le forum EDI
    Réponses: 1
    Dernier message: 25/04/2002, 13h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo