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

Concurrence et multi-thread Java Discussion :

Thread interruption (comment faire?)


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut Thread interruption (comment faire?)
    Hello,

    J'ai des thread (Callable en fait).
    Je les mets dans une liste d'attente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Executor executor = Executors.newFixedThreadPool(3);
    CompletionService<String> completionService =
                new ExecutorCompletionService<String>( executor );
     
    completionService.submit( new Th2("2.1") );
    completionService.submit( new...
     
    ...
     
    for(int i...){
      Future<String> result = completionService.take();
      System.out.println(result.get());
    }
    dans ces threads, je fais des appels systèmes. Comment est-ce que je peux faire pour que si après 1sec par exemple l'appel système n'a pas répondu, le thread se termine?
    Quelles sont les possibilités? En fait, je voudrais faire un timeout général, donc sur tous les threads, ainsi qu'un plus précis sur chaqun d'entre eux!
    Merci, A+

  2. #2
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Citation Envoyé par ploxien
    dans ces threads, je fais des appels systèmes.
    Quand tu dis appels systèmes, c'est des Runtime#exec()?

  3. #3
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut
    Quelquechose du genre
    En fait j'utilise une librairie qui fait cela mieux que Runtime#exec dans mon cas... Mais derrière, c'est ça qui est utilisé...
    C'est une librairie Shell de adiguba, touvée sur ce forum

    Pourquoi?

    Merci,
    A+

  4. #4
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Dans un thread ça aurait marché (tu fais interrupt sur le thread, ça interrompait le waitFor, et juste derrière tu fais un kill du process).
    Mais avec un Callable dans un ExecutorService, je ne sais pas comment on peut spécifier "je veux un interrupt sur CE callable"...

    EDIT: mais oui, sur ton Future<?> tu fais un cancel(true)... ! non?
    (donc il faut que tu récupères ton Future dès le submit)

  5. #5
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut
    Concrétement, si j'ai cela, je fais comment?

    Thread (callable):
    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
    import java.util.concurrent.Callable;
     
    // Callable
    public class Th1 implements Callable<String>{
     
        String name;
     
        public Th1(String name){
            this.name = name;
        }
     
        public String call() throws Exception {
            System.out.println("Start thread "+this.name);
            try {
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return new String("Return thread "+this.name);
        }
     
    }
    Classe de test:
    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
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Executor;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
     
    public class Test {
        public static void main(String[] args){
     
            Executor executor = Executors.newFixedThreadPool(3);
            CompletionService<String> completionService =
                new ExecutorCompletionService<String>( executor );
     
            completionService.submit( new Th1("1.1") );
            completionService.submit( new Th1("1.2") );
            completionService.submit( new Th1("1.3") );
            completionService.submit( new Th1("1.4") );
     
            try {
                for(int i=0;i<4;i++){
                    Future<String> result;
                    result = completionService.take();
                    System.out.println(result.get());
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    Le but serait que le thread meurt après un certain temps s'il n'est pas terminé!

    Je ne vois pas... Merci d'avance!

    A+

    edit: c'est un exemple qui ne comporte pas d'appel système, mais le principe est le même...

  6. #6
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Tu peux faire une classe qui gère le Timeout de tes futures:
    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
    public class FutureTimeout {
     
    	private static final ScheduledExecutorService TIMER = Executors.newSingleThreadScheduledExecutor();
     
    	public FutureTimeout(final Future<?> source, long delay, TimeUnit unit) {
    		Runnable cancel = new Runnable() {
    			@Override
    			public void run() {
    				source.cancel(true);
    			}
    		};
    		TIMER.schedule(cancel, delay, unit);
    	}
     
    }
    Et comme submit renvoit un Future, tu peux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Future<String> future = completionService.submit( new Th1("1.1") );
    new FutureTimeout(future);
    C'est une idée "en gros", après faut raffiner si tu veux pouvoir changer le timeout, annuler le timeout, etc...

  7. #7
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut
    Ok, ca fonctionne, mais est-ce que je peux encore, de cette manière, submitter 200 threads et ensuite attendre la première réponse que je recoit?

    Car si je dois faire un Future pour chaque thread, c'est pas super... non?
    genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Future<String> result = completionService.submit( new Th1("1.1") );
    new FutureTimeout(result, 1000, TimeUnit.MILLISECONDS);
    result = completionService.submit( new Th1("1.2") );
    new FutureTimeout(result, 1000, TimeUnit.MILLISECONDS);
    Comment faire?

    Merci, A+

  8. #8
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Citation Envoyé par ploxien
    Ok, ca fonctionne, mais est-ce que je peux encore, de cette manière, submitter 200 threads et ensuite attendre la première réponse que je recoit?

    Car si je dois faire un Future pour chaque thread, c'est pas super... non?
    genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Future<String> result = completionService.submit( new Th1("1.1") );
    new FutureTimeout(result, 1000, TimeUnit.MILLISECONDS);
    result = completionService.submit( new Th1("1.2") );
    new FutureTimeout(result, 1000, TimeUnit.MILLISECONDS);
    Comment faire?

    Merci, A+
    En fait plus proprement, change ta classe FutureTimeout en ceci:
    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
    public class FutureTimeout {
     
    	private FutureTimeout() {}
     
    	private static final ScheduledExecutorService TIMER = Executors.newSingleThreadScheduledExecutor();
     
    	public static void timeout(final Future<?> source, long delay, TimeUnit unit) {
    		Runnable cancel = new Runnable() {
    			@Override public void run() {
    				source.cancel(true);
    			}
    		};
    		TIMER.schedule(cancel, delay, unit);
    	}
     
    }
    Au passage, tu peux faire 1 SECONDS au lieu de 1000 MILLISECONDS

    Citation Envoyé par ploxien
    Car si je dois faire un Future pour chaque thread, c'est pas super... non?
    De toute façon le submit te renvoie un future, que tu l'ignores ou non

  9. #9
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut
    Oui, mais imaginons que je fasse cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Future<String> resultTemp;
            resultTemp = completionService.submit( new Th1("1.1") );
            FutureTimeout.timeout(resultTemp, 1000L, TimeUnit.MILLISECONDS);
            resultTemp = completionService.submit( new Th1("1.2") );
            FutureTimeout.timeout(resultTemp, 1000L, TimeUnit.MILLISECONDS);
    Je ne peux plus faire une boucle qui attend le premier retour, telle que celle que j'avais avant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                for(int i=0;i<4;i++){
                    Future<String> result;
                    result = completionService.take();
                    System.out.println(result.get());
                }
    Comment faire quelquechose d'identique? En sachant que le premier thread à retourner un résultat ne sera pas forcément le premier à avoir été créé, et qu'il peut y en avoir beaucour (500-1000)

    Merci

    A+

  10. #10
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467
    Par défaut
    Ah non, en fait je viens de comprendre, je peux faire cela, il faut juste que je traite le cas ou le thread est annulé...

    Je vais tester, ca devrait jouer!

    merci!

    A+

  11. #11
    Membre éclairé Avatar de ploxien
    Inscrit en
    Février 2006
    Messages
    467
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Février 2006
    Messages : 467

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

Discussions similaires

  1. Thread interrupt, comment interrompre une API tout en libérant les ressources
    Par rpelissi dans le forum Concurrence et multi-thread
    Réponses: 0
    Dernier message: 19/10/2009, 13h30
  2. Réponses: 2
    Dernier message: 26/09/2007, 16h45
  3. Comment faire du multi thread en php?
    Par sirbaldur dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 12/01/2007, 17h56
  4. [VC++/MFC] Comment faire des threads?
    Par OverLorD34 dans le forum MFC
    Réponses: 6
    Dernier message: 15/05/2006, 09h55
  5. [Thread] resume() et suspend() comment faire .
    Par ricardvince dans le forum Concurrence et multi-thread
    Réponses: 6
    Dernier message: 12/05/2006, 13h55

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