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.
3 Réponses :
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:
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'
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.
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>
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() } })
Une raison pour laquelle vous n'utilisez pas
threadPool.invokeAll (tasks);
? Mais dans votre cas, je pense que vous devez appelerthreadPool.awaitTermination ()
Je ne sais pas sur le thread Pool.invokeAll (tâches);