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

Collection et Stream Java Discussion :

[Collection] Optimisation d'un traitement multithreads


Sujet :

Collection et Stream Java

  1. #1
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut [Collection] Optimisation d'un traitement multithreads
    Bonjour,

    voilà j'ai une appli, multithread que j'aimerai optimiser. J'utilise une API propriétaire qui accède au données d'un logiciel (dans une bdd ou par calcul).
    j'espère que je vais réussir à etre clair ...

    Algo actuel :

    1. Récupérer des données (objets) avec l'API à partir d'un objet(0)
    2. Parcourir cette liste de données (avec un iterator spécifique)
    - cast de l'Object dans le bon type
    - création d'une instance "threadable" avec cet objet(1)
    - ajout de ce thread dans une liste

    3. Tous les threads sont créés. On les exécute 4 par 4

    4. pour chacun des threads :
    - chargement d'objets (2) à partir de l'objet initial (1)
    - parcours de ces objets
    - écriture des données dans un tableau. Ce tableau est ajouté dans une hasmap. Si l'élément inséré existe déjà (id), on cumule certaine valeurs.

    5. Tous les threads sont terminés. On parcours le hasmap pour insérer les données dans une bdd (avec un PreparedStatement)

    6. On vide tout et on repart avec un objet (0)

    Evolution ?
    Je me suis rendu compte que je pouvais charger directement les objets (2) à partir des objets (0)

    je voudrais donc :
    - charger tous ces objets (2) dans une Collection
    - utiliser 4 (ou plus ?) threads pour parcourir cette collection, et remplir la hasmap
    - et hop parcourir la hasmap pour insérer les données


    Enfin les questions ...

    En fait c'est des questions un peu bete je suppose ...

    • Quel type de collection est-il préférable d'utiliser ? (je cherche à gagner en performance)
    • Quelle est la meilleure manière de gérer le fait de ne pas lire 2 fois des éléments de cette collection?
    • Sachant que j'ai 4 procs, quel nombre de threads préconiser ?


    Note : je suis en 1.4 mais si le besoin se fait sentir je suppose que je peux passer en 1.5. donc utiliser des pool de threads. (serait-ce conseillé ?)

    Bon voilà.
    merci à ceux qui ont tout lu
    merci à ceux qui ont des réponses à m'apporter ...
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par in
    En fait c'est des questions un peu bete je suppose ...
    Non loin de là !


    Citation Envoyé par in
    Quel type de collection est-il préférable d'utiliser ? (je cherche à gagner en performance)
    N'importe quelle List ferais l'affaire... mais il ne faut pas oublier de la synchronisé avec Collections.synchronizedList() (ou bien de gérer toi même la synchronisation).
    Mais puisque je suppose que tu vas supprimer les éléments de la collection au fur et à mesure, je te conseille d'utiliser une LinkedList qui te permettra de supprimer le premier élément sans que cela ne soit trop couteux...

    (si tu passes à Java 5.0, regarde du coté des Queue)

    Citation Envoyé par in
    Quelle est la meilleure manière de gérer le fait de ne pas lire 2 fois des éléments de cette collection?
    La synchronisation ! Et le fait de supprimer de la liste les éléments AVANT de les traiter :
    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
    		List list = Collections.synchronizedList(new LinkedList());
     
    		// puis dans chaque thread :
    		try {
     
    			while (true) {
     
    				Object next = list.remove(0);
     
    				// Traitement de l'objet
     
    			}
     
    		} catch (IndexOutOfBoundsException e) {
    			// plus d'élément dans la liste
    		}
    Encore une fois, si tu passes à Java 5.0 tu pourrais utiliser la classe ConcurrentLinkedQueue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    		Queue<Object> queue = new ConcurrentLinkedQueue<Object>();
     
     
    		// puis dans chaque thread :
    		Object next;
    		while ( (next = queue.poll()) != null ) {
     
    			// Traitement de l'objet
     
    		}
    Citation Envoyé par in
    Sachant que j'ai 4 procs, quel nombre de threads préconiser ?
    Aucune idée...


    Citation Envoyé par in
    Note : je suis en 1.4 mais si le besoin se fait sentir je suppose que je peux passer en 1.5. donc utiliser des pool de threads. (serait-ce conseillé ?)
    Le package java.util.concurrent apporte vraiment beaucoup de classe utile...


    a++

  3. #3
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    ok, c'est parti pour la 1.5.

    le chef n'est pas là, ça lui fera une petite surprise lundi

    je teste tout ça et je pense que je vais suivre tes conseils.

    je laisse ouvert le post pour le moment, au cas où ...

    merci en tous cas !
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  4. #4
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    Bonjour,


    voilà, je suis passé en 1.5 mais je ne suis pas content de ce que j'ai fait. Et plus je lis de choses sur les possibilités de gestion des threads, plus je m'embrouille ... je reviens donc tout penaud vous poser 2 3 questions ...


    pour l'instant,

    • j'ai une ConcurentLinkedQueue que je rempli avec une liste d'objets.
    • une fois remplie, pour chaque objet, je crée un nouveau thread dans un cachedPoolThread.
    • Quand le pool de thread est rempli, je le shutdown().


    Le remplissage de la première liste d'objet est assez long (plus que l'execution des threads)
    de plus, j'ai une exception "RejectedExecutionException" lors de la deuxième itération : quand j'ajoute (execute) le premier thread au pool (le thread n'est pas null j'ai l'impression pourtant).

    est ce que le shutdown détruit mon pool ?
    [EDIT] en fait c'est normal, pares le shutdown, on ne peut plus soumettre de nouveaux threads au pool ...


    Vu que le remplissage de la liste est long, je me disais que je pourrais faire un peu du producteur/consommateur, c-a-d lancer les threads au fur et à mesure du remplissage de cette liste. Par contre je ne vois pas trop comment faire ...
    Ca va améliorer le temps de traitement ou alors il y aura trop d'attente bloquante ?

    Note :

    A la place du newCachedThreadPool, j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    threadPool = new ThreadPoolExecutor(coreSize,maxSize,timeOut,unit,new LinkedBlockingQueue<Runnable>());
    qui me parait plus sensé ...

    (j'ai la meme erreur ...)

    J'ajoute un bout de code ... si ca peux eclaircir mes explications brumeuses ...

    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
    35
    36
    37
    38
    39
    40
    41
    while(tasks.hasNext()) {   // pour chacune des activities
    						
    	Object[] data = (Object[]) tasks.next();
    	String activityOID = ((java.math.BigDecimal)data[0]).toString();
    	debutActivity = connexion.selectDateDebutActivity(activityOID);
    	finActivity = connexion.selectDateFinActivity(activityOID);
    						
    	// charge les resource assignement avec les spread data
            // ---------->    c'est tres long
            // les resourceAssignment sont des données calculées par l'API
            // (montants financiers par périodes comptables ... ) 
    	try {
    		listeRAWithLiveSpreads = proj.loadAllResourceAssignmentsWithLiveSpread( ... );
    	} catch (UndeclaredThrowableException ute) {
    	    ...
    	} catch (PhoenixException pe) {
    	    ... 
            }
    						
    	
            // ajout des données dans la ConcurrentLinkedList
    	while(listeRAWithLiveSpreads.hasNext())						              listeRA.add((ResourceAssignment)listeRAWithLiveSpreads.next());
    						
    }// fin parcours tasks du PU
    	
    	// pour chacun des RA le lance un thread
    	ResourceAssignment next = null ;
    	while( (next = listeRA.poll()) != null ) {
    		threadPool.execute(new ParallelWorkload(epsId,projId,next,debutPeriod,finPeriod,listeValeurs,connexion,proj.getDataDate()));
    	}// fin parcours des RA du CA en cours
    					
    	// tous les threads sont en attente. On ne peut plus en ajouter
    	// On les execute
    	threadPool.shutdown();
    					
    	// on attend que tout soit terminé
    	// ( timed out d'1 heure)
    	if(!threadPool.awaitTermination(3600, TimeUnit.SECONDS)) {
    		threadPool.shutdownNow();
    	}
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  5. #5
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    bonjour,

    ça y est, tout est paralléliser et ça tourne pas mal !

    j'ai pas mal galéré mais au final, le code est assez simple à mettre en place (retrospectivement) ...

    pour info ( ) je me retrouve donc avec un thread producteur et de plusieurs threads consommateur. J'ai donc utilisé une LinkedBlockingQueue pour partager mes ressources. Du coup quand le producteur termine, les consommateurs ont déjà pratiquement fini le boulot ... exactement ce qu'il me fallait ... en plus pour une découverte de java 5, c'était plutôt sympa

    donc voilà je clos le sujet.

    merci de votre aide !
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  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
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par in
    Du coup quand le producteur termine, les consommateurs ont déjà pratiquement fini le boulot ... exactement ce qu'il me fallait ... en plus pour une découverte de java 5, c'était plutôt sympa
    Si tu passes à Java 5, tu peux (même si ça n'a rien à voir avec ton problème) utiliser les générics... Ca rend le code beaucoup plus lisible et robuste...

  7. #7
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    Bonjour,

    voilà, j'ai juste une mini question ...

    Mon traitement fonctionne pas mal, j'ai juste un piti problème.

    Briefing :
    • j'ai un pool de producteurs, un pool de consommateur, une liste concurrente.
    • Un programme est composé de projets composés d'activités composées de ressources


    Afin de ne pas m'épandre, voici du pseudo 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
     
     
    Integer projId;
     
    while(programme){
     
         while(projet){
     
             // .... bref jusqu'au niveau resources
            // lecture / écriture parallèle des ressources
     
           // les pools de threads ont été exécutés
     
           // là j'ai besoin de lancer une procédure SQL
           if(containsTask) {
    		new Thread() {
     
    			public void run() {
    		             connexion.setERPCost(projId);
    			}
     
    		}.start();
    	}
     
         }//fin proj
     
    }//fin prg
    L'exécution de cette procédure SQL est à priori assez rapide quand je la lance depuis Oracle. Par contre au niveau de mon code, même si je la lance dans un thread, je me retrouve en attente de terminaison. Il ne repars pas dans un nouveau tour de boucle avant que le thread ai été exécuté.

    Alors, je me dis, ça doit être normal, que le passage au tour suivant implique que tout ai été fait ...

    Du coup mes questions :
    • est ce normal ?
    • Si oui, comment résoudre "proprement" ce genre de problème.
    • Si non, qu'ai je mal fait
    • Mon objet "connexion" est un singleton instancié par la classe parente. Cet objet étant appelé ailleurs dans la boucle, est ce qu'il vaut mieux que je passe par un pool de connexion pour favoriser le parallélisme ?


    merci d'avance
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

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

Discussions similaires

  1. Réponses: 21
    Dernier message: 20/06/2012, 16h46
  2. [8i] optimisation d'un traitement
    Par apersonnat dans le forum Administration
    Réponses: 1
    Dernier message: 22/05/2008, 14h58
  3. [MySQL] Optimisation d'un traitement arrêté par mon hébergeur
    Par lodan dans le forum PHP & Base de données
    Réponses: 17
    Dernier message: 27/02/2007, 20h37
  4. [Collection] optimisation de toArray
    Par TabrisLeFol dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 17/02/2006, 22h38
  5. [XSL] Optimisation d'un traitement de chaines de caractères
    Par mathieu dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 05/02/2006, 18h57

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