web-dev-qa-db-fra.com

Java: Comment redimensionner les threads en fonction des cœurs de processeur?

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 maths peut être séparé en unités de travail, que je veux avoir résolues en plusieurs threads.

mais je ne veux pas avoir un nombre fixe de threads travaillant dessus, mais plutôt un nombre correspondant de threads à la quantité de cœurs de processeur. 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 pourriez-vous m'aider avec un lien vers un bon tutoriel ou pourriez-vous me donner un exemple facile et bon? Ce serait vraiment gentil :)

100
Andreas Hornig

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

Mise à jour : pour préciser, un thread est simplement un objet en Java. Vous pouvez donc le créer exactement comme vous le feriez avec n'importe quel autre objet. Alors, disons que vous appelez la méthode ci-dessus et constatez qu'elle renvoie 2 processeurs. Impressionnant. Maintenant, vous pouvez créer une boucle qui génère un nouveau thread, divise le travail pour ce thread et déclenche le thread. Voici quelques pseudocodes pour illustrer 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, dirigez-vous vers ce tutoriel . En outre, vous voudrez peut-être consulter Regroupement de threads pour la création des threads.

113
JasCav

Vous voudrez probablement aussi 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<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

C'est beaucoup plus agréable que de gérer vos propres pools de threads, etc.

62
DaveC

Option 1:

newWorkStealingPool de Executors

public static ExecutorService newWorkStealingPool()

Crée un pool de threads volant le 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:

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

public static ExecutorService newFixedThreadPool(int nThreads)

remplacez nThreads parRuntime.getRuntime().availableProcessors()

Option 3:

ThreadPoolExecutor

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

passez Runtime.getRuntime().availableProcessors() comme paramètre à maximumPoolSize.

7
Ravindra babu

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

La structure Fork Join a été ajoutée à Java SE 7. Vous trouverez ci-dessous 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

7
David Soroko

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

Exemple:

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

N'oubliez pas d'arrêter le service exécuteur comme ceci (ou votre programme ne se terminera pas):

service.shutdown();

Voici juste un bref aperçu de la façon de configurer un futur code MT (offtopic, pour illustration)):

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

Ensuite, vous devez savoir combien de résultats vous attendez et les récupérer comme suit:

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

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

3
Eric Petroelje