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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    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 710
    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 710
    Points : 4 791
    Points
    4 791
    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 sénior
    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
    Points : 23 190
    Points
    23 190
    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 éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    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 710
    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 710
    Points : 4 791
    Points
    4 791
    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 sénior
    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
    Points : 23 190
    Points
    23 190
    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 éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    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

  8. #8
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    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 710
    Points : 4 791
    Points
    4 791
    Par défaut
    mon message fait entre quelques caractères et environ 500 caractères
    Euh là ...
    Cela veut dire que ton message n'est peut-être pas complet au moment où le Thread va le lire.

    Y-a-t-il une marque de début et de fin de ton message ?
    ou tout au moins une marque de fin genre "\n" ou autre pour qu'on soit sûr qu'on est au bout ?
    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/

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Citation Envoyé par Népomucène Voir le message
    ... Y-a-t-il une marque de début et de fin de ton message ?
    ou tout au moins une marque de fin genre "\n" ou autre pour qu'on soit sûr qu'on est au bout ?
    C'est un ensemble de phrases NMEA qui se répètent toutes les secondes et qui ont l'allure suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $GPGGA,151621.000,4859.6001,N,00210.4451,E,2,11,0.82,66.8,M,47.2,M,0000,0000*5C
    $GPGSA,A,3,02,10,06,30,05,07,13,09,16,23,20,,1.11,0.82,0.74*01
    $GPGSV,4,1,14,10,78,296,21,09,66,060,24,07,55,145,32,02,47,280,18*74
    $GPGSV,4,2,14,06,47,211,26,23,34,066,15,30,30,178,38,05,20,297,17*73
    $GPGSV,4,3,14,13,14,244,13,16,13,055,19,20,12,120,18,44,08,110,*72
    $GPGSV,4,4,14,29,06,336,16,03,03,117,*77
    $GPRMC,151621.000,A,4859.6001,N,00210.4451,E,2.10,148.93,201214,,,D*6B
    Selon les infos venant des satellites de la constellation GPS ces phrases sont plus ou moins complètes. Je me sers du marqueur "$GPGGA" pour scinder chaque groupe. Le thread cité plus haut envoie ces données à la procédure suivante qui fait la césure entre chaque groupe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    final Handler handlerNMEA = new Handler() { // constitution d'une phrase NMEA complète
    	public void handleMessage(Message msg) {
    		String data = msg.getData().getString("receivedData");
    		phrase = phrase+data; // on compile les infos jusqu'à ...
    		int pd = phrase.indexOf("$GPGGA"); // ce qu'on y trouve "$GPGGA"
    		if (pd >= 0) { // si trouvé ...
    			gestionInfoNMEA("$GPGGA"+phrase.substring(0, pd)); // ... récupération des données pour exploitation
    			phrase = phrase.substring(pd+6); // réinitialisation de la phrase à ce qu'il y avait en trop pour recompléter la compilation : voir début de la procédure
    		}
    	}
    };
    Cordialement.

    Pierre

  10. #10
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    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 710
    Points : 4 791
    Points
    4 791
    Par défaut
    Donc le Thread doit envoyer en permanence les données à gestionInfoNMEA qui se débrouille.

    Ceci veut dire que pour que cela fonctionne, le Thread ne doit jamais se terminer.
    On en revient à la boucle while et au sleep(500)
    et en tenant compte des remarques d'Adiguba :
    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() {
    			byte buffer[] = new byte[100];
    			while(true) {
                                     		try {
                                     			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);
                                     		}
     
                                     		try {
                                          			sleep(500); // attente d'une 1/2 seconde
                                      		} catch (InterruptedException ex) {
                                     			throw new RuntimeException(e);
                                      		}
    			}
    		}
    	}
    (en espérant ne pas me planter dans les "}")
    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/

  11. #11
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ChPr Voir le message
    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.
    Surement parce que tu fermes le flux. C'est pas top de "ne rien faire" car si un jour tu as un bug d'I/O tu ne t'en apercevras pas.

    Il faudrait surtout savoir comment est ouvert/fermé le flux, mais on ne voit rien dans le code que tu donnes.

    Le flux est utilisé uniquement dans le thread ?
    Dans ce cas il serait peut-être préférable de gérer son ouverture/fermeture dans le thread...

    Citation Envoyé par ChPr Voir le message
    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.
    Non ce qui causait la grosse consommation c'est que tu n'effectuais pas d'opération bloquante : ton code vérifie constamment s'il y a des données à lire avec available().
    En utilisant read() directement, le thread s'endort lorsqu'il n'y a rien à lire...

    C'est comme deux gosses à l'arrière d'une voiture :
    • Le premier demande toutes les 2 secondes "on est arrivé ?".
    • Le second s'endard et attend qu'on le réveille un fois arrivé.



    Citation Envoyé par ChPr Voir le message
    Dans ce que tu proposes, si k <= 0 on sort de la boucle.
    Oui... mais si k<0 cela signifie que le flux est vide, et il n'y aura plus rien à lire.
    Il est alors inutile de continuer à lire les données puisqu'il n'y en aura plus.


    Citation Envoyé par ChPr Voir le message
    Je n'ai pas pu le vérifier, mais alors, que se passe-t-il ? qui relance le thread ?
    Personne. J'ai considéré que le flux était "infini".
    S'il a une fin et qu'il faut le lancer il faudra le gérer, mais c'est la même chose pour ton code, sauf que lui il continuera de vérifier qu'il n'y a "rien" 80000 par seconde...


    Citation Envoyé par ChPr Voir le message
    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 ?
    512 ? 1024 ?
    Franchement aucune idée, mais si les données ne sont pas trop grande il est préférable de prendre un buffer pouvant les contenir d'un coup.

    Tes données sont envoyés ligne par ligne ?
    Dans ce cas le plus simple serait d'utiliser un BufferedReader et readLine()...


    Citation Envoyé par Népomucène Voir le message
    On en revient à la boucle while et au sleep(500)
    Pourquoi le sleep(500) ? read() endort déjà le thread si besoin et le réveille au plus tôt.
    Cela ne fait que rajouter un délai de 500ms inutilement...


    a++

  12. #12
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Je ne rappelerait qu'une chose qu'un grand bonhomme de Java m'a une fois dite:

    On ne devrait jamais avoir à utiliser "sleep()"... si on utilise sleep dans un code, c'est qu'on a oublié un élément de synchronisation (Object.wait() / Object.signal() ) ou qu'on a omis de passer par des fonctions bloquantes.


    Le throw new RuntimeException() ne sert à rien.... "InterruptedException" indique qu'on doit s'arrêter (le thread doit mourrir) donc il faut sortir !
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  13. #13
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    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 710
    Points : 4 791
    Points
    4 791
    Par défaut
    C'est intéressant ce sujet, je n'avais pas encore regardé la "blocabilité" d'un Inputstream.

    @adiGuba tu suggères le code suivant (voir plus haut) :
    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);
    		}
    	}
    Je n'ai pas l'impression que le Thread va être bloqué sur la ligne while ((k = receiveStream.read(buffer, 0, 100)) > 0)
    Il me semble que k va recevoir une valeur dans tous les cas : le nombre de bytes ou -1 s'il n'y a plus rien à lire.

    Donc, à ce stade, le Thread se termine toujours et n'est pas relancé (tu as d'ailleurs suggéré dans le post suivant qu'il fallait le faire).
    J'ai donc proposé de mettre le code dans une boucle qui me semblait plus simple que de recréer le Thread 2 fois par secondes.
    Et comme il ne faut pas que ça tourne 80.000 fois par seconde, il m'a aussi semblé plus simple d'ajouter sleep(500).

    Naturellement, je serai très intéressé par un meilleurs code que sleep(500).
    Par ailleurs, ce que je connais ne concerne que java "classique". Je ne sais pas comment réagit java "Android".
    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/

  14. #14
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Népomucène Voir le message
    Je n'ai pas l'impression que le Thread va être bloqué sur la ligne while ((k = receiveStream.read(buffer, 0, 100)) > 0)
    Il me semble que k va recevoir une valeur dans tous les cas : le nombre de bytes ou -1 s'il n'y a plus rien à lire.
    Tu te trompe sur -1 : il n'est pas retourné s'il n'y a pas de données à lire, mais uniquement si on atteint la fin du flux (généralement cela signifie que le flux a été fermé de l'autre coté).
    S'il n'y a rien à lire dans le flux (la source n'a pas encore écrit de données), alors read() bloquera et endormira le thread courant jusqu'à la réception des données.

    Du coup la boucle que j'ai donné fait parfaitement l'affaire. read() bloquera le thread courant jusqu'à recevoir des données.

    Citation Envoyé par Népomucène Voir le message
    Donc, à ce stade, le Thread se termine toujours et n'est pas relancé (tu as d'ailleurs suggéré dans le post suivant qu'il fallait le faire).
    J'ai donc proposé de mettre le code dans une boucle qui me semblait plus simple que de recréer le Thread 2 fois par secondes.
    Et comme il ne faut pas que ça tourne 80.000 fois par seconde, il m'a aussi semblé plus simple d'ajouter sleep(500).
    Non le thread se termine uniquement si le flux est fermé.
    Et si c'est le cas cela ne sert à rien de le maintenir en vie car en toute logique read() renverra toujours -1.
    Dans ton cas ton thread va continuer à tourner indéfiniment pour rien car il ne devrait plus recevoir de données.

    Après je ne sais pas si cela peut survenir ou pas (je ne connais pas la source du flux), mais si cela arrive il faut fermer le flux et en ouvrir un autre.
    Mais en l'état le thread n'a pas les moyen de le faire, car ce n'est pas lui qui ouvre le flux.


    tu te compliques la vie avec des problèmes qui n'existent pas.


    a++

  15. #15
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par nicroman Voir le message
    On ne devrait jamais avoir à utiliser "sleep()"... si on utilise sleep dans un code, c'est qu'on a oublié un élément de synchronisation (Object.wait() / Object.signal() ) ou qu'on a omis de passer par des fonctions bloquantes.
    Hey! le sleep est bien pratique dans un unit test. Contrairement à un élément bloquant, on est sur que le travail reprend après X secondes. Alors qu'avec un synchro, si elle échoue (c'est un unit test, c'est sensé trouver les cas où ça échoue), c'est le serveur d'intégration continue qui est bloqué

    Puis ça me laisse le temps de lire les fenêtres ouvertes par le test unitaire

  16. #16
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    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 710
    Points : 4 791
    Points
    4 791
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Tu te trompe sur -1 : il n'est pas retourné s'il n'y a pas de données à lire, mais uniquement si on atteint la fin du flux
    C'est en effet ce que dit la doc.

    ChPr a écrit : C'est un ensemble de phrases NMEA qui se répètent toutes les secondes
    Du coup il faudrait qu'il fasse un test pour savoir si entre deux envois, le Stream est fermé ou non.
    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/

  17. #17
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Si le flux est fermé, aucun des codes postés ne pourra marcher...


    a++

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Citation Envoyé par Népomucène Voir le message
    ... Du coup il faudrait qu'il fasse un test pour savoir si entre deux envois, le Stream est fermé ou non.
    J'ai mis du temps à répondre car j'ai voulu analyser ce fameux "stream".

    La configuration : un GPS blueTooth "GlobalSat BT-821C" et mon smartPhone "Samsung Galaxy S2".

    Dans la boucle du thread, j'ai inclus l'enregistrement de la variable "data" à chaque passage. J'ai fixé mon buffer à 512. Selon que j'utilise la méthode avec le "sleep" ou l'autre, j'ai des résultats "instantanés" différents, mais au global, le fonctionnement est la même.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	String data = new String(buffer, 0, k);
    // ci-après, une instruction qui enregistre le nombre d'octets "k", la date du système et les données "data" du buffer							
    	FCH.ecrit(String.format("%d - ", k)+GPS.getDate(System.currentTimeMillis(), "dd-MMM-yy HH:mm:ss")+"  "+data, fchBT);
    Ce que je vois au travers du fichier de données :

    • Lorsque mon GPS et le smartphone sont proches, il y a un flux ininterrompu de données.
    • Si j'éloigne le GPS du smartphone de telle manière qu'il ne soit plus à portée de réception pour une dizaine de secondes, le flux existe toujours et si je reviens dans l'espace de réception, le flux reste ininterrompu.
    • Si maintenant, je m'éloigne assez longtemps, environ une vingtaine de secondes, alors le flux s’interrompt. Si dés lors, je me rapproche du smartphone, dans une méthode comme dans l'autre, le flux ne reprend pas pas.

    Je pense qu'il se passe ce qui suit :

    au bout d'un certain temps, le "système BlueTooth" doit se dire que le liaison est perdue et qu'il faut la réinitialiser. Ce qui se traduit par :

    1. pour la méthode avec le sleep : on ne sort pas du thread (boucle while(true)), mais il n'y a plus rien à recevoir : il faut réinitialiser le tout,
    2. pour l'autre méthode, dès lors que le buffer interne du "BlueTooth" du smartphone est vide, on sort du thread. Comme il n'y a rien pour le faire repartir et que de toute façon, à une poignée de secondes de différence entre le moment où le buffer est vide et celui ou la liaison radio est rompue, la liaison est rompue, il faut réinitialiser le tout.

    La différence de fonctionnement entre les deux méthodes :

    • avec le sleep : pratiquement, à chaque passage dans le thread, le buffer comprend un grand nombre d’octets, on va dire 300 en moyenne,
    • avec l'autre méthode, le nombre d'octets transmis est beaucoup plus saucissonné. Avec cette méthode, lorsque je me déconnecte où que la liaison est perdue, je passe par la case "exception" ???

    Si cela vous intéresse , je peut vous joindre un fichier où figurent les enregistrements.

    Cordialement.

    Pierre

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Je constate que ce que tu proposes fonctionne parfaitement. Pour autant, j'avoue ne toujours pas comprendre.

    Citation Envoyé par adiGuba Voir le message
    ... En utilisant read() directement, le thread s'endort lorsqu'il n'y a rien à lire...
    Que veut dire "rien à lire" ? si je lis l'instruction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	while ((k = receiveStream.read(buffer, 0, 512)) > 0) {
    		...
    pour moi, "rien à lire" veut dire que k <= 0 parce que le buffer est vide et dès lors, je sors de la boucle puis je sors du thread. Je ne vois pas ce que veut dire "le thread s'endort" ?

    D'ailleurs, tu le confirmes en disant :

    Citation Envoyé par adiGuba Voir le message
    ... Oui... mais si k<0 (moi, j'avais écrit k <= 0) cela signifie que le flux est vide, et il n'y aura plus rien à lire.
    Il est alors inutile de continuer à lire les données puisqu'il n'y en aura plus. ...
    ... ??? ...

    Je crois que je viens de comprendre. peut-être vas-tu me confirmer ou m'infirmer ce que je crois comprendre :

    la notion de flux et de contenu du flux sont deux choses différentes. Un flux peut exister avec un contenu "nul" et l'instruction "read" constatant que le flux existe mais qu'il n'offre aucune donnée attend patiemment qu'il y en ait. "read" renverra -1 lorsque le "flux" et non pas son contenu n'existera plus. J'ai bon ?

    Cordialement.

    Pierre

  20. #20
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    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 710
    Points : 4 791
    Points
    4 791
    Par défaut
    @ChPr : merci de ton retour, c'est intéressant de savoir "pour de vrai" comment se comporte ce flux.

    Je serai aussi très intéressé par le code que tu vas utiliser finalement.
    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/

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

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