Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

problème de wait sur l'exécution d'une commande java

3 réponses
Avatar
Bonjour,

J'utilise Process p = Runtime.getRuntime().exec(commande,null,dir_exécution)
pour lancer une commande java dans un répertoire donné et ensuite je teste
son résultat.

Ca fonctionne (fichier de sortie créé) sauf que le test est négatif car le
processus n'est pas terminé au moment où il est fait.

J'ai donc rajouté p.waitFor() pour attendre que le processus se termine et
là il ne rend pas la main. p.wait() n'est guère mieux.

J'ai vu sur le net que c'est probablement une histoire de bufferisation mais
je ne maîtrise pas.

Il y a aussi la solution d'utiliser un Thread mais je maîtrise encore moins.

Je cherche donc un secours ici :)

Merci pour votre aide.

3 réponses

Avatar
Yliur
Le Fri, 30 Aug 2013 19:21:18 +0200
<meta> a écrit :

Bonjour,

J'utilise Process p > Runtime.getRuntime().exec(commande,null,dir_exécution) pour lancer
une commande java dans un répertoire donné et ensuite je teste son
résultat.

Ca fonctionne (fichier de sortie créé) sauf que le test est négatif
car le processus n'est pas terminé au moment où il est fait.

J'ai donc rajouté p.waitFor() pour attendre que le processus se
termine et là il ne rend pas la main. p.wait() n'est guère mieux.

J'ai vu sur le net que c'est probablement une histoire de
bufferisation mais je ne maîtrise pas.

Il y a aussi la solution d'utiliser un Thread mais je maîtrise encore
moins.

Je cherche donc un secours ici :)

Merci pour votre aide.



Il est possible qu'il faille lire les tampons de sortie de ton
processus pour éviter qu'ils ne se remplisse. Donc une bidouille avec
plusieurs fils d'exécution (avec Thread par exemple). Il existe aussi
une méthode simplifiée avec une méthode utilitaire de java dans les
versions récentes, mais j'ai oublié ce que c'est. Quelques mots-clés
bien sentis dans un moteur de recherche devraient vous permettre de
retrouver ça facilement, sinon je refouillerai.

Par contre je ne comprends pas bien ce que signifie "lancer une
commande java" ici. Ce mécanisme sert à lancer une commande externe
(par exemple un programme exécutable existant sur le système). Si le
but est de lancer un traitement en parallèle, Thread/Runnable est plus
simple. Encore que dans ce cas je ne vois pas bien l'intérêt d'attendre
que le processus se termine, autant exécuter le code java directement.

Quel est l'objectif exact
Avatar
Il est possible qu'il faille lire les tampons de sortie de ton


processus pour éviter qu'ils ne se remplisse. Donc une bidouille avec
plusieurs fils d'exécution (avec Thread par exemple). Il existe aussi
une méthode simplifiée avec une méthode utilitaire de java dans les
versions récentes, mais j'ai oublié ce que c'est. Quelques mots-clés
bien sentis dans un moteur de recherche devraient vous permettre de
retrouver ça facilement, sinon je refouillerai.

Par contre je ne comprends pas bien ce que signifie "lancer une
commande java" ici. Ce mécanisme sert à lancer une commande externe
(par exemple un programme exécutable existant sur le système). Si le
but est de lancer un traitement en parallèle, Thread/Runnable est plus
simple. Encore que dans ce cas je ne vois pas bien l'intérêt d'attendre
que le processus se termine, autant exécuter le code java directement.

Quel est l'objectif exact



Bonsoir, merci pour votre réponse. Le but était de lancer l'exécution d'un
jar dont le but é tait de créer un fichier de sortie mais cela prenait trop
de temps el te processus rendait la main avant la fin de la création.
J'avais donc rajouté l'attente qui du coup se bloquait. J'ai fini par
trouver sur le net qu'en fait le blocage était du au fait que les sorties
(standard, erreur) n'étaient pas vidées et en rajoutant des threads
consommateurs (j'ai bêtement recopié l'exemple), ça a débloqué l'attente.
Mais j'avoue que j'aurais aimé voir une solution n'utilisant que les Thread,
pour voir car si on n'a pas déjà vu quelqu'un le faire, c'est difficile
d'intuiter....
Avatar
Yliur
Le Mon, 2 Sep 2013 21:45:59 +0200
<meta> a écrit :

>Il est possible qu'il faille lire les tampons de sortie de ton
processus pour éviter qu'ils ne se remplisse. Donc une bidouille avec
plusieurs fils d'exécution (avec Thread par exemple). Il existe aussi
une méthode simplifiée avec une méthode utilitaire de java dans les
versions récentes, mais j'ai oublié ce que c'est. Quelques mots-clés
bien sentis dans un moteur de recherche devraient vous permettre de
retrouver ça facilement, sinon je refouillerai.

Par contre je ne comprends pas bien ce que signifie "lancer une
commande java" ici. Ce mécanisme sert à lancer une commande externe
(par exemple un programme exécutable existant sur le système). Si le
but est de lancer un traitement en parallèle, Thread/Runnable est plus
simple. Encore que dans ce cas je ne vois pas bien l'intérêt
d'attendre que le processus se termine, autant exécuter le code java
directement.

>Quel est l'objectif exact

Bonsoir, merci pour votre réponse. Le but était de lancer l'exécution
d'un jar dont le but é tait de créer un fichier de sortie mais cela
prenait trop de temps el te processus rendait la main avant la fin de
la création. J'avais donc rajouté l'attente qui du coup se bloquait.
J'ai fini par trouver sur le net qu'en fait le blocage était du au
fait que les sorties (standard, erreur) n'étaient pas vidées et en
rajoutant des threads consommateurs (j'ai bêtement recopié
l'exemple), ça a débloqué l'attente. Mais j'avoue que j'aurais aimé
voir une solution n'utilisant que les Thread, pour voir car si on n'a
pas déjà vu quelqu'un le faire, c'est difficile d'intuiter....



Une solution simplifiée pour Java 7 est présentée ici :
http://blog.developpez.com/adiguba/p8040/java/processbuilder_redirect

Pour la solution sans processus complet (donc avec seulement des fils
d'exécution dans le programme) :
- Ce n'est possible que si le code du jar peut être utilisé depuis
l'appli principale (il faut par exemple que le jar soit dans le
chemin des classes de l'appli, comme les autres bibliothèques de
l'application par exemple).
- Il suffit d'exécuter la méthode main() de la classe principale de
ce jar exécutable.
- Même pas besoin de créer un fil d'exécution supplémentaire,
puisque le but est juste d'attendre que ce soit terminé ;) . Un
simple appel de fonction suffit.

Sinon pour créer des fils d'exécution en Java c'est très simple :
- Créer une classe (même interne ou anonyme, mais pour la dernière
ce n'est pas très joli à mon goût). Cette classe doit tout
simplement implémenter l'interface Runnable, qui possède une
unique méthode run (voir la javadoc).
- Pour lancer un fil d'exécution, qui n'est jamais qu'un nouveau
pointeur dans le code avec sa propre pile (la pile d'appels des
fonctions par exemple), mais qui utilise le tas commun (les
objets alloués par tout le monde), il suffit d'écrire quelque
chose comme ça (en supposant que ma classe TraitementAsynchrone
implémente Runnable) :
Thread filExec = new Thread (new TraitementAsynchrone) ;
filExec.start() ;
- Un nouveau pointeur d'exécution est créé dans le code, mais si
les deux fils (l'ancien et le nouveau) possèdent des références
vers des objets communs ils peuvent tous les deux accéder à ces
objets, donc attention aux accès concourants.
- À la place d'implémenter Runnable, il est possible de créer une
classe héritant de Thread et de redéfinir sa méthode run. Si la
nouvelle classe s'appelle TraitementAsynchrone, le lancement donne
ça :
TraitementSynchrone filExec = new TraitementSynchrone() ;
filExec.start() ;

La doc de la classe Thread ici par exemple :
http://docs.oracle.com/javase/6/docs/api/

L'équivalent de waitFor() est join().