2
votes

Comment atteindre 1000 points de terminaison en utilisant le multi threading dans Groovy?

Je dois atteindre les points de terminaison plus de 1 000 fois pour récupérer des données sur le site Web. J'ai donc lu quelques tutoriels pour utiliser Multi Threading pour y parvenir. Mais à la fois, je veux utiliser seulement 13 threads sur la même méthode .

Donc, en gros, j'utilise ExecutorService pour exécuter 13 threads à la fois:

@Override
        void run() {
            println("In run method...................")
            try {
                Thread.sleep(5000);
                someMethod()
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

Ma classe Groovy nommée ScraperService est en train de mettre en œuvre l'interface Runnable .

ExecutorService threadPool = Executors.newFixedThreadPool(13);
for (int itLocation = 0; itLocation < locationList.size(); itLocation++) {
  //some code like
  ScraperService obj = new ScraperService(threadName,url)
  threadPool.submit(obj);
}
threadPool.shutdown();
Problème:

Mon problème est que mon ExecutorService.submit (obj) et ExecutorService.execute (obj) n'appelle pas ma méthode run () de l'interface Runnable.

Dans Groovy / Grails:

Il existe également un plugin exécuteur Executor Plugin in grails mais je n'ai trouvé aucun exemple approprié pour l'utiliser.


2 commentaires

Une raison pour laquelle vous n'utilisez pas threadPool.invokeAll (tasks); ? Mais dans votre cas, je pense que vous devez appeler threadPool.awaitTermination ()


Je ne sais pas sur le thread Pool.invokeAll (tâches);


3 Réponses :


1
votes

le threadPool.submit n'exécute pas la tâche

utilise threadPool.execute (obj) ou threadPool.submit (obj) .get ()

au lieu de threadPool.submit(obj)

consultez la documentation pour plus de détails:

https://docs.oracle .com / javase / 7 / docs / api / java / util / concurrent / ExecutorService.html # submit (java.util.concurrent.Callable)

exemple:

import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


ExecutorService pool=Executors.newFixedThreadPool(3)

for(int i=0;i<7;i++){
    int x=i;
    Thread.sleep(444);
    pool.execute{
        println "start $x"
        Thread.sleep(3000+x*100);
        println "end   $x"
    }
}

println "done cycle"
pool.shutdown()                 //all tasks submitted
while (!pool.isTerminated()){}  //waitfor termination
println 'Finished all threads'


2 commentaires

Donc, si je veux exécuter 1000 threads, je devrais utiliser hreadPool.submit (obj) .get () pour chaque thread. En fait, en utilisant également la méthode threadPool.execute (obj), mon appel ne va pas être remplacé par la méthode run ().


Si vous utilisez execute (), vous n'aurez aucun moyen de savoir si votre exécutable a été exécuté. En utilisant submit (), vous devez sauvegarder tous les Futures retournés, puis les boucler en vérifiant get (). Faites attention aux exceptions interrompues. Guava's Futures.getUnchecked () peut être d'une grande aide ici.



2
votes

GPars est excellent pour ce type de chose.

Votre ScraperService peut simplement être responsable de la gestion des données récupérées comme ci-dessous ou peut-être de les récupérer aussi, peu importe.

import groovyx.gpars.GParsPool

def theEndpoint = 'http://www.bbc.co.uk'

def scraperService

GParsPool.withPool( 13 ) {
    (1..1000).eachParallel {
        scraperService.scrape theEndpoint.toURL().text
    }
}

p>


0 commentaires

1
votes

Tout d'abord, je pense qu'il y a un problème dans la classe service groovy avec l'annotation @Transnational qui ne permet pas d'appeler la méthode run () de l'interface Runnable. Si vous supprimez le @Transnational , il appellera la méthode run (). C'est arrivé aussi dans mon cas. Mais je ne suis pas sûr, il peut y avoir une autre raison. Vous pouvez utiliser directement:

ExecutorService threadPool = Executors.newSingleThreadExecutor();

Extra (Au fur et à mesure que je lis votre question)

Si vous utilisez plusieurs threads sur la même méthode, il peut être complexe car tous les threads utiliseront les mêmes variables locales de cette méthode, ce qui peut poser des problèmes. Il est préférable d'utiliser plusieurs threads pour différents travaux.

Mais si vous souhaitez utiliser la même méthode pour exécuter plusieurs threads, dans mon scénario, il est préférable d'utiliser Executors.newSingleThreadExecutor().

ExecutorService threadPool =  Executors.newFixedThreadPool(13)
threadPool.execute(new Runnable() {
                            @Override
                            void run() {
                                Thread.sleep(5000);
                                someMethod()
                            }
                        })


0 commentaires