Multi Thread

“Bonjoir” la Caf’ & tous mes champions de g€€k qui m’int déjà aidé auparavant.

Après avoir réussi à faire un MIDLet qui se connecter à un GPS et affiche les trames j’ai besoin de développer un calcul de distance via les coordonnées des trames GPGGA (gps au norme nmea décrite ici ).

J’arrive à parser et récupérer ce que je veux donc dans le MIDlet que je fais j’ai supposé les trames déjà parsées et les coordonnées déjà séparées pour plus de simplicité (je regrouperai le tout plus tard).

Bref l’idée est de s’attaque au multi thread l’un s’occupe de récupérer les coordonnées dans un vecteur.
Ce vecteur enregistre les coordonnées sous la forme
(departlatitude, departlongitude, arrivéelatitude, arrivée longitude)

ce que je souhaite c’est dès qu’il a une size de 4 je fais une pause pour ce thread et je lance le second qui lui calcule la distance parcourue et me l’affiche(dans la console pour le moment).

Il faudrait ensuite que celui ci redonne la main au premier etc jusqu’à ce que mon tableau soit lu jusqu’à la fin.(au final ca sera un stream qui sera lu en temps réel dès réception des trames gps parsées…).

Bon alors je débute donc si je suis pas clair dites le moi, mon code est faux et je le sais mais je le laisse volontairement comme cela pour ce soir car il traduit bien ce que je souhaite faire.

Merci aux courageux qui m’ont lu et à ceux qui m’aideront.

Le Duc.

Re coucou.

Je cut 'n paste ce qu’effectue le thread1 qui est censé préparé les coordonnées pour etre calculées par le thread 2.

Il utilise donc un vecteur qui lorsqu il est de taille 4 est envoyé au second thread:
-taille 4 parceque comme dit plus haut (departLat, departLong, arrivéeLat, arrivéeLong).

Au final seul il marche bien.
Voilà ce qu’affiche la console.

Il décompose donc le tableau du main() qui simule la réception des trames reçues & parsées.

{0,40,2,48,4,44,5,10,47,12,13,51}


(long;lat) : (0.0;40.0)
(long;lat) : (2.0;48.0)
(long;lat) : (4.0;44.0)
(long;lat) : (5.0;10.0)
(long;lat) : (47.0;12.0)
(long;lat) : (13.0;51.0)

taille du vecteur 1
0.0,
taille du vecteur 2
0.0,40.0,
taille du vecteur 3
0.0,40.0,2.0,
taille du vecteur 4
0.0,40.0,2.0,48.0,
taille du vecteur 2
2.0,48.0,
taille du vecteur 3
2.0,48.0,4.0,
taille du vecteur 4
2.0,48.0,4.0,44.0,
taille du vecteur 2
4.0,44.0,
taille du vecteur 3
4.0,44.0,5.0,
taille du vecteur 4
4.0,44.0,5.0,10.0,
taille du vecteur 2
5.0,10.0,
taille du vecteur 3
5.0,10.0,47.0,
taille du vecteur 4
5.0,10.0,47.0,12.0,
taille du vecteur 2
47.0,12.0,
taille du vecteur 3
47.0,12.0,13.0,
taille du vecteur 4
47.0,12.0,13.0,51.0,
taille du vecteur 2
13.0,51.0,


Merci à tous.

Le Duc.

Déjà une question : Pourquoi faire une pause ? Je veux dire par là que ton thread qui choppe les données a-t-il vraiment d’attendre que le 2e thread calcule la distance avec les 4 premières entrées du Vecteur pour continuer son exécution ?

Ne serait-il pas plus intéressant, donc, de faire tourner ton thread T1 (celui qui choppe les données) et tous les 4 éléments ajoutés à ton vecteur, il envoie un signal à T2 avec les infos pour calculer la nouvelle distance.

Bonjour rorotaz et encore merci de m’aider (une nouvelle fois).

Pour ce qui est de faire une pause ca n’est pas nécéssaire en effet mais je n’arrive pas à lancer mon thread n°2 à partir du premier lorsque celui ci a son vecteur en taille 4.

Juste une idée comme ça :

Dans ton main (ou autre), tu crées ThreadCalcul et ThreadChoppe (Thread de Calcul et l’autre de Choppage de données).
Mais tu donnes à ThreadChoppe une référence de ThreadCalc. En gros :

ThreadCalcul gloubi = new ThreadCalcul(); ThreadChoppage boulga = new ThreadChoppe(gloubi);

A ThreadCalcul tu ajoutes une méthode qui calcule une distance et une autre qui retourne le total des distances calculées.
A chaque fois que ThreadChoppe récupère une valeur, il calcule si la taille du vecteur est modulo 4 (if ((monVector.size() % 4) == 0) quoi), et dans ce cas, il appelle la méthode calculDistance de ThreadCalcul dont il a la référence (donnée dans le constructeur).

A la fin du schnoutz, quand tu as tout calculé, grâce à la méthode getDistanceTotale de ThreadCalcul, tu récupères la distance.

Est-ce clair ?

(ce n’est là qu’une idée à la va vite, donc pas optimale du tout je pense)

[quote=“rorotaz, post:4, topic: 30505”]Juste une idée comme ça :

Dans ton main (ou autre), tu crées ThreadCalcul et ThreadChoppe (Thread de Calcul et l’autre de Choppage de données).
Mais tu donnes à ThreadChoppe une référence de ThreadCalc. En gros :

ThreadCalcul gloubi = new ThreadCalcul(); ThreadChoppage boulga = new ThreadChoppe(gloubi);

A ThreadCalcul tu ajoutes une méthode qui calcule une distance et une autre qui retourne le total des distances calculées.
A chaque fois que ThreadChoppe récupère une valeur, il calcule si la taille du vecteur est modulo 4 (if ((monVector.size() % 4) == 0) quoi), et dans ce cas, il appelle la méthode calculDistance de ThreadCalcul dont il a la référence (donnée dans le constructeur).

A la fin du schnoutz, quand tu as tout calculé, grâce à la méthode getDistanceTotale de ThreadCalcul, tu récupères la distance.

Est-ce clair ?[u]

(ce n’est là qu’une idée à la va vite, donc pas optimale du tout je pense)[/quote]

Vi vi c’est clair et ca parait assez logique.
Je testerai tout ca demain ou ce soir de chez moi(oui j’aime bien bosser chez moi B) .

Encore une fois j’apprends en même temps que je découvre donc ne pas hésiter à me montrer mes Grosses Nerreurs.
(et oui encore une fois merci)

Je repost dès demain .

Le_Duc> Je n’avais pas trop regardé ton code, donc je ne peux pas dire si tu as fait ou pas des grosses erreurs.
Ma solution, c’est juste la 1e idée qui me soit venue pour résoudre ce problème et qui me paraisse à peu près viable.
Maintenant, c’est toujours un plaisir de pouvoir aider quelqu’un B) N’hésite pas à poster si tu as d’autres problèmes…

Plop ici.
(Désolé de te pm pour ca mais) j’ai bien peur que le « dredi c’est permis » prenne le pas sur mon post B) .

J’ai essayé de faire comme tu voulais pour les threads mais ca n’est pas possible les constructeurs des thread étant fonction de parametre et non de thread.

De plus je ne vois pas comment lui demander de lancer le thread de calcul étant donné que :

  • dans mon main il ne voit pas le vecteur de choppage (qui quand il atteint 4 est censé amener le lancement du second thread)
  • quand je le lance depuis mon thread de choppage j’ai 17 warning et la console n’affiche que

(long;lat) : (0.0;40.0)
(long;lat) : (2.0;48.0)
(long;lat) : (4.0;44.0)
(long;lat) : (5.0;10.0)
(long;lat) : (47.0;12.0)
(long;lat) : (13.0;51.0)

taille du vecteur 1
0.0,
taille du vecteur 2
0.0,40.0,
taille du vecteur 3
0.0,40.0,2.0,
taille du vecteur 4
0.0,40.0,2.0,48.0,

En gros le thread calc ne se lance pas :confused:

ps: je peux te passer le code tel que je l’exécute si tu veux check ca de plus près. JMMPP powa

EDIT : j’ai abandonné l’idée du pm(faut bien laisser les gens vivre^^)

EDIT 2: => PS

Le_Duc, pour ton problème de constructeur, je ne l’ai pas précisé dans mon post, mais il suffit que ta classe ThreadChoppage étende la classe Thread. Par exemple :

[code]public class ThreadChoppage extends Thread {

private ThreadCalcul calcul = null;

public ThreadChoppage(ThreadCalcul tc) {
	this.calcul = tc;
}

public void run() {
	// le code ici pour ton thread
	monVecteur.add(...);
	if ((monVecteur.size() % 2) == 0) {
		calcul.calculDistance(// Tu donnes tes paramètres ici);
	}
	// suite du code ici...
}

}[/code]

Personnellement, je ne vois pas ThreadChoppage lancé ThreadCalcul. C’est ton main qui démarre les 2 threads, mais grâce au code ci-dessus, ThreadChoppage, qui a une référence à ThreadCalcul, peut demander à ce dernier d’exécuter le calcul des distances dès que 4 éléments sont ajoutés au vecteur.

[quote=“rorotaz, post:8, topic: 30505”]Le_Duc, pour ton problème de constructeur, je ne l’ai pas précisé dans mon post, mais il suffit que ta classe ThreadChoppage étende la classe Thread. Par exemple :

Personnellement, je ne vois pas ThreadChoppage lancé ThreadCalcul. C’est ton main qui démarre les 2 threads, mais grâce au code ci-dessus, ThreadChoppage, qui a une référence à ThreadCalcul, peut demander à ce dernier d’exécuter le calcul des distances dès que 4 éléments sont ajoutés au vecteur.[/quote]

Le problème c’est que je ne peux pas lancer threadCalc depuis le main parcequ’il a besoin d’avoir un vecteur en paramètre.
Après au niveau logique c’est évident qu’il faudrait que je lance les deux depuis le main et que le Tchoppage appelle l’autre de calcul quand son vecteur est de taille 4.

De plus tu m’avais dit de faire référence juste à une méthode du thread de calcul depuis le thread de choppage mais je n’ai pas de fonction de calc dans le thread calc tout ca est intégré dans son run() en gros si tu as :

L’appel du calcul se fait juste en faisant
t2.start();

Je me répète mais j’essaie d’assimiler le concept de thread alors c’est peut être la façon dont je les ai codé qu’il faut que je revois plus que leur utilisation.

Merci B)

Une solution, comme ça rapidement pour coder ton Thread de calcul :

[code]public class ThreadCalcul extends Thread {

private long distanceTotale = 0;
private boolean cEstFiniMonCoco = false;

public ThreadCalcul() {
	distanceTotale = 0;
	cEstFiniMonCoco = false;
}

public void calculDistance(Object a, Object b, Object c, Object d) {
	long distance = 0;
	// Je fais le calcul selon les 4 éléments.
	distanceTotale += distance;
}

public long getDistanceTotale() {
	return (distanceTotale);
}

public void run() {
	try {
		// Tant qu'on appelle pas la méthode arreteMoi, le Thread tourne en boucle...
		while (!cEstFiniMonCoco) {
			Thread.sleep(250);
		}
	} catch (Exception e) {
	}
}

// Quant on appelle cette méthode, ça va terminer the Thread.
public void arreteMoi() {
	cEstFiniMonCoco = true;
}

}[/code]

Maintenant, dans ton main, tu initialises les 2 Threads en donnant une référence de ThreadCalcul à ThreadChoppage.
Quand toutes les distances sont calculées, tu appelles getDistanceTotale() puis arreteMoi() du Thread.

ps: Pour les PM, je n’ai rien contre, mais n’étant pas un Java guru, d’autres personnes peuvent participer à la discussion et donner leur avis, donc c’est préférable de rester sur le thread…

[quote=“Le_Duc, post:9, topic: 30505”]L’appel du calcul se fait juste en faisant
t2.start();[/quote]

Juste pour répondre à ça :
Dans mon code, tu fais un t2.start() pour démarrer le thread, mais celui-ci ne fait rien si ce n’est d’attendre.
En fait, t2 va attendre qu’on appelle calculeDistance() pour calculer une distance.

Je vais être lourd mais j’ai envie non seulement d’y arriver mais surtout de comprendre.

Je ne peux pas faire référence au Thread de calcul quand j’instancie le premier.

ThreadCalc2 tCalc = new ThreadCalc2(); ThreadData tData = new ThreadData (tCalc);

Il me dit que le constructeur n’est pas défini avec tCalc en parametre ce qui est logique vu que le constructeur est pour l’instant fait pour recevoir un tableau en paramètre.

Je comprend pas trop là.
Dans ton code de ThreadData, tu as bien ajouté un constructeur prenant un ThreadCalc2 ?
En code :

[code]public class ThreadData extends Thread {

private ThreadCalc2 calcul = null;

public ThreadData(ThreadCalc2 tc) {
	this.calcul = tc;
}

...[/code]

Sans ça, il est évident que tu ne pourras pas donner de référence de ThreadCalc2 à ThreadData.

Tu peux aussi faire ça :

[code]public class ThreadData extends Thread {

private ThreadCalc2 calcul = null;

public ThreadData() {
	// Initialization du Thread.
}

public void setThreadCalc2(ThreadCalc2 tc) {
	this.calcul = tc;
}

...[/code]

et dans le main :

ThreadCalc2 tCalc = new ThreadCalc2(); ThreadData tData = new ThreadData (); tData.setThreadCalc2(tCalc);

Ca revient au même, c’est un poil plus long quoi.

[quote=“rorotaz, post:12, topic: 30505”]Je comprend pas trop là.
Dans ton code de ThreadData, tu as bien ajouté un constructeur prenant un ThreadCalc2 ?
En code :

[code]public class ThreadData extends Thread {

private ThreadCalc2 calcul = null;

public ThreadData(ThreadCalc2 tc) {
	this.calcul = tc;
}

...[/code]

Sans ça, il est évident que tu ne pourras pas donner de référence de ThreadCalc2 à ThreadData.[/quote]

Bon ok en fait dans mon projet j’ai modifié la classe ThreadCalc et pas la ThreadCalc2 donc boulet powa.

Pour passer au problème suivant (et oui ca serait trop facile), quand je lance le main y a rien qui s’éxécute.
Juste 2o warnings, je pense que ca vient du fait que du coup le thread de choppage n’a plus de tableau en paramètres et du coup plus rien à chopper.

Pourrais-tu reposter tes nouvelles sources, que j’y jette un oeil ?

Voilà,
par contre je ne me sers pas de la classe ThreadCalc juste de ThreadCalc2.

Je prends tous les conseils & recommandations B)

Merci rorotaz.

Oui donc y a une erreur de null pointer exception parceque le thread choppage n’a plus de données à chopper.
Enfin de ce que j’ai compris du moins.

J’ai pris tes sources.
Déjà, j’ai dû initialiser tabData dans ThreadData (sinon, NullPointerException).
Ensuite, j’ai dû modifier vData.addElement([b]new Double/b);, mais là, c’est juste parce que moi je tourne avec un JDK 1.4 et toi avec un 1.5 (avec Java 5, ça se fait automatiquement, mais avec 1.4, tu ne peux pas ajouter un type primitif dans un vecteur directement). Là, passons.

Ensuite, c’est normal que ton code ne fasse rien (si ce n’est de l’affichage) : en effet, ThreadCalc2 n’est jamais appelé.
Quand tu as 4 éléments dans ton vecteur, tu ne fais rien si ce n’est virer les 2 premiers élements. Donc voici ce qu’il faut faire dans le for du ThreadData :

for (int i=0;i<tabData.length;i++) { vData.addElement(new Double(tabData[i])); // Si 4 éléments (mon if est plus rapide qu'un switch, et plus lisible if ((vData.size()) % 4) == 0) { // Je prends les 2 premières valeurs et les vire de mon vecteur... double d1 = ((Double) vData.removeElement(vData.firstElement())).doubleValue(); double d2 = ((Double) vData.removeElement(vData.firstElement())).doubleValue(); // Je récupère les 2 autres valeurs en les laissant dans mon vecteur... double d3 = ((Double) vData.get(0)).doubleValue(); double d4 = ((Double) vData.get(1)).doubleValue(); // Maintenant, je peux calculer la distance... calcul.calculDistance(d1, d2, d3, d4); } }

Edit : Commentaires
Sinon, il faudra penser à arrêter les 2 threads dès lors que tu n’as plus d’éléments (sinon les threads vont continuer à tourner sans cesse).

Voilà ma nouvelle boucle (la tienne ne passait pas en copier coller pour certains trucs)
Donc là je récupère les valeurs dans les variables je calcule et je nettoie les deux premières places du vecteur.

for (int i=0;i<tabData.length;i++) { vData.addElement(new Double(tabData[i])); // Si 4 éléments (mon if est plus rapide qu'un switch, et plus lisible if ((vData.size()% 4) == 0) { //Je récupère les 4 valeurs pour le calcul... double d1 = ((Double) vData.get(0)).doubleValue(); double d2 = ((Double) vData.get(1)).doubleValue(); double d3 = ((Double) vData.get(2)).doubleValue(); double d4 = ((Double) vData.get(3)).doubleValue(); // Maintenant, je peux calculer la distance... calcul.calculDistance(d1, d2, d3, d4); //Je prends les 2 premières valeurs et les vire de mon vecteur... vData.removeElement(vData.firstElement()); vData.removeElement(vData.firstElement()); } }

Par contre y a toujours le problème du tableau… tu dis qu’il faut l’instancier dans le threaddata mais si je l instancie ici ca veut dire que ce thread ne va rien chercher s’il a déjà les données mais bon je vais tester quand même?

PS: pour prendre un pot dis moi ^^

Je t’avouerais que je ne vois pas trop la différence entre nos 2 boucles.
Moi, dans mon cas, j’enlève les 2 premiers éléments du vecteur, mais je les stocke dans d1 et d2. Donc le vecteur diminue de taille, mais les valeurs ne sont pas perdues car stockées dans des variables (d1 et d2).
Bon, je me suis gouré par contre, c’est normal qu’il fasse une erreur. La méthode removeElement retourne un booléen, pas l’élément. Ce qu’il fallait faire donc :

for (int i=0;i<tabData.length;i++) { vData.addElement(new Double(tabData[i])); // Si 4 éléments (mon if est plus rapide qu'un switch, et plus lisible if ((vData.size()) % 4) == 0) { // Je prends les 2 premières valeurs et les vire de mon vecteur... double d1 = ((Double) vData.remove(0)).doubleValue(); // Pensez à récupérer l'élément à l'index 0, pas 1, vu que le vecteur a été diminué dans la ligne du dessus. double d2 = ((Double) vData.remove(0)).doubleValue(); // Je récupère les 2 autres valeurs en les laissant dans mon vecteur... double d3 = ((Double) vData.get(0)).doubleValue(); double d4 = ((Double) vData.get(1)).doubleValue(); // Maintenant, je peux calculer la distance... calcul.calculDistance(d1, d2, d3, d4); } }

Toutefois, ça ne devrait pas changer grand chose, c’est juste de l’optimisation là.

Pour ton initialisation, je disais cela a des fins de tests.

Ma question : Est-ce que ThreadData récupère le tableau de données d’un seul coup ou pas ? Il me semble que non.
Je modifie les sources selon ma nouvelle idée, je re-poste ensuite d’ici 10 minutes.

Pour le pot, je garde ta proposition sous le coude B)

Bon là ca passe me reste à stopper les thread quand tout a été traité etc etc.

=> Faut surtout que le thread qui récupère les données le fasse et ne se serve pas d’un tableau instancié dans sa classe :confused: <=

En tout cas merci bôôôôcoup.
Je continue à bosser dessus.

rorotaz> Pour ton pot attends début septembre que j’ai mes sous de smicar B)

ca ressemble au serveur que j’ai concu pour ma boite, sauf que l’archi est un peu differente, j’ai 1 thread qui recoit les requetes, et qui les envoies dans un thread pool pour creer une reponse et l’envoyer.

ca me semblait plus efficace quand le nombre de données a gerer devient important, ou alors que tu a besoin/que tu peut et veut le distribuer.

edit: oops, my fault, je parlais de C#, ne connaissant pas les threads en java, je sais pas si ce concept est applicable facilement