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

Java Discussion :

Un garde-fou pour mes Threads


Sujet :

Java

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 43
    Points : 42
    Points
    42
    Par défaut Un garde-fou pour mes Threads
    Bonjour,

    Je suis face à un problème de multithread et j'aurais besoin d'un coup de main pour trouver une solution.

    Mon système actuel :

    J'ai un main qui exécute plusieurs threads d'après une liste de tache. La liste de tache étant très longue je limite le nombre de thread simultané grâce à un compteur que j'incrémente quand un thread est lancé et que je décrémente lorsqu'il se termine. Lorsque la limite du nombre de thread est atteinte je met le main en attente sur une variable de condition. Un signal est lancé à chaque fois qu'un thread se termine.

    Voici le code :
    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
    for (Page page : pages)
    {
    	synchronized(this.threadMonitor)
    	{
    		while(this.nbThread >= this.settings.getMaxThread())
    		{
    			try
    			{
    				this.threadMonitor.wait();
    			}
    			catch (InterruptedException e)
    			{System.err.println("InterruptedException - threadMonitor.wait");}
    		}
     
    		this.nbThread++;
     
    		threadPages[count] = new ThreadElement(page);
    		threadPages[count].start();
     
    		count++;
    	}
    }
     
    for (ThreadElement thread : threadPages)
    {
    	try
    	{
    		thread.join();
    	}
    	catch (InterruptedException e)
    	{
    		e.printStackTrace();
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void decremNbThread()
    {
    	synchronized (this.threadMonitor)
    	{
    		this.nbThread--;
     
    		this.threadMonitor.notify();
    	}
    }
    Ceci fonctionne bien mais je voudrais aller plus loin.

    Mon problème :

    Je veux que chaque thread ainsi créé puisse lui aussi créer des threads d'après une sous liste de tache tout en conservant la limite totale de thread.
    Mais d'après moi un tel système peut être bloquant car chaque thread peut attendre une place pour exécuter une sous tache mais sans libérer sa place.
    Ma première idée est de compter un thread en attente comme ne faisant pas partie du compte, si un thread veut lancer ses fils il commencer par décrémenter le compteur. Mais j'ai peur que le nombre de thread en attente s'envole.


    Mes questions :

    Existe il une façon de résoudre le problème que j'ai énoncé ?
    Dans le main, le fait que beaucoup de threads soit en attente du join est il un problème ? (plusieurs milliers)
    Si je veux que les sous-taches se fassent en priorité, la méthode Thread.setPriority peut elle m'aider ? Comment ?


    Ça fait beaucoup de question en suspend, j'espère que quelqu'un saura me répondre

  2. #2
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Tu essayes de réinventer la roue !
    Mais c'est une bonne chose, ça veut dire que tu as des idées.

    Ce dont tu as besoin se trouve dans la classe Executors qui permet de créer des Pools de Threads réutilisables, dont certains pools ont une taille limitée (FixedThreadPool).
    Ces objets permettront de gérer la création/utilisation de threads.

    Je te laisse donc regarder/chercher tout ce qui se fait avec les ThreadPools et les Executors
    En gros, ça se passe comme ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Runnable r = new MyRunnable();
    Executor ex = Executors.newCachedThreadExecutor();
    ex.execute(r);
    ...
    ex.shutdown(); // quand tu as fini
    ...
    if (!ex.isTerminated(){
        List<Runnable> executionsPasTerminees = ex.shutdownNom(); // si ça ne veut pas finir
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    for (ThreadElement thread : threadPages)
    {
    	try
    	{
    		thread.join();
    	}
    	catch (InterruptedException e)
    	{
    		e.printStackTrace();
    	}
    }
    Dans cette boucle, tu dis grosso modo : attends jusqu'à ce que tous les threads soient terminés. C'est bien ce que tu veux faire?
    Au niveau impacts, y'a pas de problème si c'est ce que tu veux effectivement faire, mais ça peut être long s'il y en a beaucoup !

    Si je veux que les sous-taches se fassent en priorité, la méthode Thread.setPriority peut elle m'aider ? Comment ?
    En théorie oui, mais en pratique, tu n'as aucune façon de savoir si la JVM que tu utilise va respecter ce que tu lui demandes. (a savoir, passer en priorité l'exécution d'un nouveau Thread à niveau de priorité plus important plutôt que de finir celui qui est en cours)
    Si tu veux être sûr de l'ordre, il faudrait stocker tes Threads dans une PriorityQueue (file qui permet de classer les éléments par priorité en fonction de leur ordre compareTo) qui est consommée par ton "moteur" : chaque fois que ton moteur va vouloir lancer un Thread, il les prendra dans l'ordre que TU as spécifié.
    Pour ne pas surcharger la queue de Threads, il faut préciser une taille de queue max dans le constructeur de ta PriorityQueue et ajouter des éléments à la file en utilisant la méthode offer() (qui renvoie true si tu as pu ajouter l'élément, sinon à toi d'attendre et de boucler jusqu'à ce que la méthode te renvoie 'true')

    Sinon, tu peux aussi passer par une LinkedTransferQueue qui ajoute la méthode offer() qui attend tout seul qu'il y ait de la place (mais ça ne sera pas classé :/)
    Je ne suis pas mort, j'ai du travail !

  3. #3
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    +1 pour les ExecutorService.

    J'utiliserais un awaitTermination( de faire le shutdown() (sinon, les sous-tâches qui ne pourraient ne pas avoir encore été lancées seront rejetées).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    J'apprends toujours beaucoup de choses utiles quand je poste sur ce forum, merci pour les réponses et la réactivité.

    Je vais me documenter sur les FixedThreadPool ca semble effectivement être une bonne idée, merci.

  5. #5
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    Pour donner priorité aux sous-tâches tu peux regarder du côté de Fork/Join.

    Pour savoir si tu as terminées tes tâches, tu peux utiliser :
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 43
    Points : 42
    Points
    42
    Par défaut
    Voici ce que j'obtiens en suivant vos conseils. C'est basiquement les mêmes mécaniques que ce que j'avais mis en place mais en plus propre et performant.

    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
    this.executor = Executors.newFixedThreadPool(this.settings.getMaxThread());
    this.doneSignal =  new CountDownLatch(this.pages.size());
     
    for (Page page : pages)
    {
    	this.executor.execute(new ThreadElement(page, this.doneSignal));
    }
     
    try
    {
    	this.doneSignal.await();
    }
    catch (InterruptedException e)
    {
    	e.printStackTrace();
    }
     
    this.executor.shutdown();
    Je n'utilise pas encore les sous-taches mais je sens que ca va poser problème étant donné que le CountDownLatch demande le nombre total de tache alors que je ne connais pas à l'avance le nombre de sous-taches de chaque tache.

  7. #7
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    Tu peux également regarder le framework Fork/Join, il dispose d'une API qui simplifie la gestion des sous-tâches.

    De cette manière tu pourras également faire un invokeAll à la place du CountDownLatch
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

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

Discussions similaires

  1. Serveur FTP - Lequel choisir pour mes besoins
    Par etumed dans le forum Réseau
    Réponses: 3
    Dernier message: 19/03/2006, 13h58
  2. [RCP][plug-ins]Jars pour mes plugins dans un client RCP??
    Par tophebboy dans le forum Eclipse Platform
    Réponses: 5
    Dernier message: 14/03/2006, 16h56
  3. Réponses: 7
    Dernier message: 11/04/2005, 22h23
  4. Aperçu pour mes types de fichiers
    Par Aurelien.Regat-Barrel dans le forum Windows
    Réponses: 3
    Dernier message: 27/09/2004, 18h33
  5. Comment créé une "interface" pour mes programmes??
    Par alcazar dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 09/02/2004, 13h02

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