Multi Thread

Je vais poser une question con, mais je connais pas Java donc j’ai le droit de poser des questions cons B)
Est-ce que tu peux faire des évènement ?

Bon, voilà la nouvelle classe toute belle ThreadData :

[code]import java.util.Vector;

public class ThreadData extends Thread {

private Vector vData = new Vector();
private ThreadCalc2 calcul = null;
private boolean finished = false;
private static final long SLEEP = 100; // Temps de repos (en ms), a modifier selon les besoins.

/**
 * Initialisation du Thread avec une reference de ThreadCalc2.
 **/		 
public ThreadData(ThreadCalc2 tc) {
	this.calcul = tc;
	finished = false;
}

/**
 * Ajoute une nouvelle valeur (longitude, latitude).
 **/		 
public synchronized void addNouveauLieu(double lon, double lat) {
	vData.add(new Double(lon));
	vData.add(new Double(lat));
}

/**
 * Quand on veut terminer le thread, on met le booleen a true, ce qui stoppera la boucle de run().
 **/			 
public void stopMe() {
	finished = true;
}

public void run(){
	while (!finished) {
		// Teste si le vecteur contient 4 elements ou pas. 
		if ((vData.size()) % 4) == 0) {
			double d1 = ((Double) vData.removeElement(vData.firstElement())).doubleValue();
			double d2 = ((Double) vData.removeElement(vData.firstElement())).doubleValue();
			double d3 = ((Double) vData.get(0)).doubleValue();
			double d4 = ((Double) vData.get(1)).doubleValue();
			calcul.calculDistance(d1, d2, d3, d4);
		}
		try {
			Thread.sleep(SLEEP);
		} catch (Exception e) {
		}
	}
}

}[/code]

Et le main :

public static void main (String [] args){ ThreadCalc2 tCalc = new ThreadCalc2(); ThreadData tData = new ThreadData (tCalc); tData.start(); tCalc.start(); for (int i = 0; i < tab.length; i += 2) { tData.addNouveauLieu(tab[i], tab[i + 1]); } tData.stopMe(); // Pense a ajouter, comme dans ThreadData, une methode stopMe a ThreadCalc2. tCalc.stopMe(); }

Edit :

[quote=“Galad, post:21, topic: 30505”]Je vais poser une question con, mais je connais pas Java donc j’ai le droit de poser des questions cons B)
Est-ce que tu peux faire des évènement ?[/quote]

Bien sûr. Après, ça dépend du type d’évènement que tu souhaites catcher.
C’est quoi ton idée au juste ? (même si j’ai une idée)

Edit 2 : Je n’ai pas compilé non plus, donc on n’est pas à l’abri d’une petite erreur de typo par ci, pas là.
Pas trop d’explications, si tu en veux, dis-moi. Mais globalement mon idée :
Main file des données 2 par 2 à ThreadData, qui les ajoute dans un Vecteur. Dès qu’il en a 4, il les file à ThreadCalcul.
Ah, j’ai oublié un truc avant d’arrêter mes threads :

public static void main (String [] args){ ThreadCalc2 tCalc = new ThreadCalc2(); ThreadData tData = new ThreadData (tCalc); tData.start(); tCalc.start(); for (int i = 0; i < tab.length; i += 2) { tData.addNouveauLieu(tab[i], tab[i + 1]); } long distanceTotale = tCalc.getDistanceTotale(); tData.stopMe(); // Pense a ajouter, comme dans ThreadData, une methode stopMe a ThreadCalc2. tCalc.stopMe(); }

rorotaz si je te demande de me coder une appli qui fait du café tout en me réservant un A/R Montréal pour septembre 2009 en classe affaire tout en m’affichant les résultats soprtifs de l’année tu me dis quoi ?

  • avec rorotaz c’est possible *

Grand merci à toi je manipule encore un peu ( et surtout ta boucle qui marche toujours pas notamment l’abus de tes parenthèses ^^)

Y a du 4 v 3 t’es dur B)

Encore une fois merci à toi.

Mon MIDlet avance…

Ben l’idée serait de créer un évènement dans ton main() pour signaler qu’un vecteur est “chopé” (appelont le chopeEvent) et un autre pour signaler que le calcul est terminé (appelons le calculEvent)

chopeEvent prends en paramètre le vecteur. Quand, dans le thread de chopage le vecteur est trouvé, tu lance l’évènement chopeEvent, avec ton vecteur en paramètre. Dans chopeEvent, tu vas lancer ton thread de calcul avec le vecteur qui a été donné en paramètre.
Le thread de calcul est lancé, quand il est fini, tu lève lance l’évènement calculEvent, avec les résultats de tes calculs en paramètre, qui seront récupérés dans ton main.

Maintenant j’ai pas trop suivi ce que vous avez dit ce matin donc faut adapter…

Pour Le_Duc

[quote=« Le_Duc, post:23, topic: 30505 »]rorotaz si je te demande de me coder une appli (…)

Grand merci à toi je manipule encore un peu ( et surtout ta boucle qui marche toujours pas notamment l’abus de tes parenthèses ^^)

(…)[/quote]

Pour l’appli, aucun souci. Faut juste me financer B) (et prendre un billet pour moi aussi).
Pour les parenthèses, j’ai fait ça à l’arrache avec PSPad, j’ai pas calculé les parenthèses, ça m’arrive souvent. En fait c’est :

if ((vData.size() % 4) == 0) { ... }

Pour Galad

Grosso-modo, c’est ce qu’on fait. Sauf que les évènements sont un peu cachés.
Par exemple, quand on fait :

if ((vData.size() % 4) == 0) { ... calcul.calculeDistance(...); }

ça peut s’assimiler à l’évènement Quand mon vecteur est de taille modulo 4, alors calcule moi la distance.
Donc en gros, j’ai codé un peu ton idée.

En Java, les évènements sont surtout (mais pas uniquement) liés aux interfaces graphiques (genre quand on clique sur un bouton, quand on fait défiler une liste, etc.).

Edit : Clean post.

Pour les parenthèses y a np sur Eclipse ca saute aux yeux et c’est une erreur tellement minime que bon ca se corrige vite fait.
Par contre j’ai scruté ton code et adapté le main rajouté les stop() là où il fallait pour stopper l autre thread.

Mais là quand je lance ca ne fait rien apparemment les threads sont actifs mais rien dans la console n’est retourné je pense que ca doit venir du vecteur qui ne se rempli pas.

Je regarde ca de plus près et je te dis.

PS : Pour le Canada je pars y vivre dès que j’y peux t’auras tous les billets d’avions que tu veux si je parviens à y vivre:)

J’ai modifié le code pour afficher le Vecteur histoire de voir ce qui cloche:

public synchronized void addNouveauLieu(double lon, double lat) { System.out.println("on rempli le vecteur vData : "); //vData.add(lon); //vData.add(lat); vData.add(new Double(lon)); vData.add(new Double(lat)); if(vData.size()>0){ for (int i = 0; i <= vData.size(); i++){ System.out.print("("+vData.get(i)+")"); } } }

La console m’affiche :


on rempli le vecteur vData :
0.0 40.0


En allant chercher à bouffer, j’ai pensé à un truc : il faut locker les accès au vecteur. En théorie ça ne devrait poser aucun problème, puisque on retire les éléments en début de tableau tandis qu’on ajoute à la fin, mais c’est plus propre :

[code]import java.util.Vector;

public class ThreadData extends Thread {

private Vector vData = new Vector();
private ThreadCalc2 calcul = null;
private boolean finished = false;
private static final long SLEEP = 100; // Temps de repos (en ms), a modifier selon les besoins.
private boolean lock = false;

/**
 * Initialisation du Thread avec une reference de ThreadCalc2.
 **/		
public ThreadData(ThreadCalc2 tc) {
	this.calcul = tc;
	finished = false;
	lock = false;
}

/**
 * Ajoute une nouvelle valeur (longitude, latitude).
 **/		
public synchronized void addNouveauLieu(double lon, double lat) {
	try {
		while (!locked) {
			// Ici on attend quand le Vecteur est locké.
			Thread.sleep(100);
		}
	} catch (Exception e) {
	}
	vData.add(new Double(lon));
	vData.add(new Double(lat));
}

/**
 * Quand on veut terminer le thread, on met le booleen a true, ce qui stoppera la boucle de run().
 **/			
public void stopMe() {
	finished = true;
}

public void run(){
	while (!finished) {
		// Teste si le vecteur contient 4 elements ou pas.
		if ((vData.size() % 4) == 0) {
			// On va toucher au vecteur, donc on locke.
			lock = true;
			double d1 = ((Double) vData.remove(0)).doubleValue();
			double d2 = ((Double) vData.remove(0)).doubleValue();
			double d3 = ((Double) vData.get(0)).doubleValue();
			double d4 = ((Double) vData.get(1)).doubleValue();
			lock = false;
			calcul.calculDistance(d1, d2, d3, d4);
		}
		try {
			Thread.sleep(SLEEP);
		} catch (Exception e) {
		}
	}
}

}[/code]

Edit : mauvais copié collé

Edit : Je me suis un peu planté, je réédite bientôt avec du bon code source qui marche (compilé et testé)

Hmmm bien joué ( par contre change ta variable lock en locked ou l’inverse ^^ )

Sinon ca te donne quoi quand tu exécutes moi ca me lance le debug et rien de plus. Y a toujours un problème avec le fait de remplir le vecteur je pense pourtant au niveau du code je vois pas.

J’ai changé toujours le bout de code pour le vecteur comme suit:

[code] while (!finished) {
// Teste si le vecteur contient 4 elements ou pas.
if ((vData.size() % 4) == 0) {
// On va toucher au vecteur, donc on locke.
locked = true;
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();
locked = false;
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());

		}
		try {
			Thread.sleep(SLEEP);
		} catch (Exception e) {
		}
	}[/code]

Je pense pas qu’il y ait d’erreur pourtant il me plante :confused:

Le Duc (revenu de sa pause déjeuner).

Bon, voilà un meilleur code :

[code]import java.util.Vector;

public class ThreadData extends Thread {

private Vector vData = new Vector();
private ThreadCalc2 calcul = null;
private boolean finished = false;
private static final long SLEEP = 10; // Temps de repos (en ms), a modifier selon les besoins.
private boolean lock = false;

/**
 * Initialisation du Thread avec une reference de ThreadCalc2.
 **/		
public ThreadData(ThreadCalc2 tc) {
	this.calcul = tc;
	finished = false;
	lock = false;
}

/**
 * Ajoute une nouvelle valeur (longitude, latitude).
 **/		
public synchronized void addNouveauLieu(double lon, double lat) {
	try {
		while (lock) {
			// Ici on attend quand le Vecteur est locké.
			Thread.sleep(100);
		}
	} catch (Exception e) {
	}
	vData.add(new Double(lon));
	vData.add(new Double(lat));
}

/**
 * Quand on veut terminer le thread, on met le booleen a true, ce qui stoppera la boucle de run().
 **/			
public void stopMe() {
	while (vData.size() > 2) {
		launchCalcul();
	}
	finished = true;
	calcul.stopMe();
}

private void launchCalcul() {
	if (vData.size() >= 4) {
		// On va toucher au vecteur, donc on locke.
		lock = true;
		double d1 = ((Double) vData.remove(0)).doubleValue();
		double d2 = ((Double) vData.remove(0)).doubleValue();
		double d3 = ((Double) vData.get(0)).doubleValue();
		double d4 = ((Double) vData.get(1)).doubleValue();
		lock = false;
		calcul.calculeDistance(d1, d2, d3, d4);
	}
}

public void run(){
	while (!finished) {
		// Teste si le vecteur contient 4 elements ou pas.
		if ((vData.size() != 0) && (vData.size() % 4) == 0) {
			launchCalcul();
		}
		try {
			Thread.sleep(SLEEP);
		} catch (Exception e) {
		}
	}
}

}[/code]

J’ai ajouté :

  1. une méthode launchCalcul qui enlève les éléments du vecteur et demande le calcul à ThreadCalcul.
  2. Quand on demande au Thread de se terminer, il va d’abord regarder si le contenu du Vecteur est supérieur à 2 éléments (je dis 2 parce qu’on ne supprime pas les 2 derniers éléments du Vecteur quand on calcule la dernière distance).
  3. Je stoppe le Thread de calcul via ce Thread et non plus dans le main (pour éviter de stopper le thread de calcul alors que le thread de data n’a pas terminé).

Tout ça manque encore d’optimisation, mais on s’approche de quelque chose déjà B)

Bon en fait la condition avec le modulo 4 n’est pas bonne (j’ai testé et on entre dans le IF dès le début)
et donc il plante parceque quand le vecteur est de taille 0 il n’a aucune valeur à attribuer à d1.

J’ai remplacé la condition par

(vecteur.size()) == 4)

Et là je ne rentre pas dans le if mais par contre rien ne se passe.

Le problème doit venir du vecteur qui ne se rempli pas.

B) wala wala :smiley:

EDIT : cela concerne le POST d’avant pas le dernier que tu as posté :stuck_out_tongue:
Le dernier je viens de le mettre en place. il faut juste qu’il se termine parcequ’apparemment un thread ne se ferme pas.
Je regarde ca de plus près.
Merci encore.

ps: t’auras bien mérité des cahuètes avec ta bière;)

Effectivement, il y avait un problème avec la taille du vecteur quand il est vide.
C’est effectivement résolu avec la dernière version.

Edit : Evite de mettre la condition if (vData.size() == 4), parce que si ton vecteur se remplit trop vite, alors tu peux être dans le cas où la taille est plus grande que 4, et dans ce cas, ton thread ne calculera plus rien. Donc fait plutôt if ((vData.size() != 0) && ((vData.size() % 4) == 0)) { ….
A la limite, même mieux :
if (vData.size() >= 4) { …
Dans ce cas, tu calcules dès que tu as au moins 4 éléments.

Pour les cahouètes, je passe. Je pourrais avoir 2 bières B)

Des bières tu veux des bières tu auras B) .

Tite soirée radio biere foot avec bataille de joysticks ou claviers choisis ton arme :smiley:

Bon je retourne au code faut que j’intègre ca dans mon MIDlet qui récupère et parse déjà les trames du gps.
Tout un boulot quoi. :stuck_out_tongue:

PS: les ingé viennent de se rendre compte que personne ne m’a brieffé sur ce projet car le brief a été fait pour 2 personnes en juillet et aucune n’est là (une en vac et l’autre chez un client).
bref une entrée en matière assez brutale.

Encore une fois rorotaz :smiley: .

Si je peux me permettre, votre algo est basé sur du polling, qu’il soit ralenti (sleep) ou non. C’est cracra B)
Le principe auquel ça me fait penser est l’algo de base dit du producteur/consommateur (chacun étant un thread). Il est préférable de jouer avec des évenements sur lesquels les deux protagonistes attendront et signaleront en fonction de la situation. Pour faire simple, “Je signal que j’ai produit et j’attend d’avoir le droit de reproduire” pour le producteur et “j’attends que les données soient prêtes puis je signal une fois que j’ai consommé” pour le consommateur.

Je ne dis pas que votre truc ne foncitonne pas (je n’ai d’ailleurs pas lu précisément) mais rien que de voir des boucles avec des sleep, ça fait mal au c*@$.

Juste une petite remarque de principe.

J’ai toujours le problème des threads qui restent en RUNNABLE .

mon main ressemble à ca.

[code]public static void main (String [] args){
ThreadCalc2 tCalc = new ThreadCalc2();
ThreadData3 tData = new ThreadData3 (tCalc);

	tData.start();
	for (int i = 0; i < tab.length; i += 2) {
		tData.addNouveauLieu(tab[i], tab[i + 1]);
	}
	tCalc.start();
	
	double distanceTotale = tCalc.getDistanceTotale();
	System.out.println(tData.getState());
	tData.stopMe();
	System.out.println(tData.getState());
	}
}[/code]

La console me renvoie ca :


RUNNABLE
917.7686114726907
497.25890073235837
3774.3538390531903
4679.26178605199
5241.067335734719
RUNNABLE


A vrai dire, l’idéal serait de se servir des classes proposés dans java.util.concurrent, l’une des nouveautés de Java 5. Hélas, n’ayant pas encore eu la chance de pouvoir coder en Java 5, je n’ai pu mettre tout ceci en application dans le problème de Le_Duc.
Donc Le_Duc, je te conseille de regarder ces classes et de trouver des tutoriaux dessus, ça peut aider.

[quote=“Le_Duc, post:36, topic: 30505”][code]public static void main (String [] args){
ThreadCalc2 tCalc = new ThreadCalc2();
ThreadData3 tData = new ThreadData3 (tCalc);

	tData.start();
	for (int i = 0; i < tab.length; i += 2) {
		tData.addNouveauLieu(tab[i], tab[i + 1]);
	}
	tCalc.start();
	
	double distanceTotale = tCalc.getDistanceTotale();
	System.out.println(tData.getState());
	tData.stopMe();
	System.out.println(tData.getState());
	}
}[/code][/quote]

Quelques soucis : Il faut démarre tCalc avant la boucle for, puisqu’en théorie, tData, qui reçoit les données au fur et à mesure de l’exécution de la boucle, va appeler tCalc. Donc démarre le avant le for.
Idem, le getDistanceTotale, il est préférable de faire comme suit :

tData.stopMe(), à la fin, va arrêter tCalc. Mais juste avant ça, il va lui demander la distance totale calculée. Ensuite, tData.stopMe() va retourner la distance totale, qu’il aura récupéré depuis le Thread de calcul. En gros:

Dans tCalc :

public long stopMe() { finished = true; return (distanceTotale); }

Dans tData :

public long stopMe() { while (vData.size() > 2) { launchCalcul(); } finished = true; // Retourne la distance totale. return (calcul.stopMe()); }

Du coup, dans le Main, tu n’as qu’à appeler tData.stopMe(), puisque c’est ce dernier qui se chargera de stopper tCalc.