Java: Comment faire évoluer les threads en fonction de cœurs de processeurs?

Je ne suis pas un bon programmeur java, c’est juste mon passe-temps, mais j’ai hâte d’en savoir plus que la moyenne.

Je veux résoudre un problème mathématique avec plusieurs threads en Java. mon problème de math peut être séparé en unités de travail, que je veux avoir résolu en plusieurs threads.

mais je ne veux pas avoir un nombre fixe de threads, mais plutôt un nombre de threads correspondant au nombre de cpu. Et mon problème est que je ne pouvais pas trouver un tutoriel facile sur Internet pour cela. tout ce que j’ai trouvé sont des exemples avec des threads fixes.

Alors, pouvez-vous m’aider avec un lien vers un bon tutoriel ou pourriez-vous me donner un exemple facile et bon? Ce serait vraiment gentil 🙂

Vous pouvez déterminer le nombre de processus disponibles sur la machine virtuelle Java à l’aide de la méthode Runtime statique, availableProcessors . Une fois que vous avez déterminé le nombre de processeurs disponibles, créez ce nombre de threads et divisez votre travail en conséquence.

Mise à jour : pour clarifier davantage, un thread n’est qu’un object en Java, vous pouvez donc le créer comme vous le feriez pour tout autre object. Alors, disons que vous appelez la méthode ci-dessus et trouvez qu’elle renvoie 2 processeurs. Impressionnant. Maintenant, vous pouvez créer une boucle qui génère un nouveau thread et diviser le travail pour ce thread, et déclenche le thread. Voici un pseudo-code pour démontrer ce que je veux dire:

int processors = Runtime.getRuntime().availableProcessors(); for(int i=0; i < processors; i++) { Thread yourThread = new AThreadYouCreated(); // You may need to pass in parameters depending on what work you are doing and how you setup your thread. yourThread.start(); } 

Pour plus d'informations sur la création de votre propre thread, rendez-vous sur ce tutoriel . En outre, vous pouvez regarder le regroupement de threads pour la création des threads.

Vous voulez probablement regarder le framework java.util.concurrent pour ce genre de choses. Quelque chose comme:

 ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // Do work using something like either e.execute(new Runnable() { public void run() { // do one task } }); 

ou

  Future future = pool.submit(new Callable() { public Ssortingng call() throws Exception { return null; } }); future.get(); // Will block till result available 

C’est beaucoup plus agréable que de faire face à vos propres pools de threads, etc.

Doug Lea (auteur du paquet simultané) a ce document qui peut être pertinent: http://gee.cs.oswego.edu/dl/papers/fj.pdf

Le framework Fork Join a été ajouté à Java SE 7. Voici quelques références supplémentaires:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html Article de Brian Goetz

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

Option 1:

newWorkStealingPool des Executors

 public static ExecutorService newWorkStealingPool() 

Crée un pool de threads voleur de travail en utilisant tous les processeurs disponibles comme niveau de parallélisme cible.

Avec cette API, vous n’avez pas besoin de transmettre le nombre de cœurs à ExecutorService .

Implémentation de cette API à partir de grepcode

 /** * Creates a work-stealing thread pool using all * {@link Runtime#availableProcessors available processors} * as its target parallelism level. * @return the newly created thread pool * @see #newWorkStealingPool(int) * @since 1.8 */ public static ExecutorService newWorkStealingPool() { return new ForkJoinPool (Runtime.getRuntime().availableProcessors(), ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); } 

Option 2:

API newFixedThreadPool des Executors ou other newXXX constructors , qui renvoie ExecutorService

 public static ExecutorService newFixedThreadPool(int nThreads) 

remplacez nThreads par Runtime.getRuntime().availableProcessors()

Option 3:

ThreadPoolExecutor

 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) 

transmettez Runtime.getRuntime().availableProcessors() tant que paramètre à maximumPoolSize .

Sur la classe Runtime, il existe une méthode appelée availableProcessors (). Vous pouvez l’utiliser pour déterminer le nombre de processeurs que vous avez. Puisque votre programme est lié au processeur, vous voudrez probablement avoir (au plus) un thread par processeur disponible.

La méthode standard est la méthode Runtime.getRuntime (). AvailableProcessors (). Sur la plupart des processeurs standard, vous avez renvoyé le nombre de threads optimal (qui ne correspond pas au nombre de cœurs de processeur). C’est donc ce que vous recherchez.

Exemple:

 ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 

N’oubliez pas de fermer le service exécuteur comme ceci (ou votre programme ne se terminera pas):

 service.shutdown(); 

Voici un bref aperçu de la mise en place d’un futur code MT (offtopic, pour illustration):

 CompletionService completionService = new ExecutorCompletionService(service); ArrayList> futures = new ArrayList>(); for (Ssortingng computeMe : elementsToCompute) { futures.add(completionService.submit(new YourCallableImplementor(computeMe))); } 

Ensuite, vous devez suivre le nombre de résultats attendus et les récupérer comme ceci:

 try { int received = 0; while (received < elementsToCompute.size()) { Future resultFuture = completionService.take(); YourCallableImplementor result = resultFuture.get(); received++; } } finally { service.shutdown(); }