Principes de base du multithreading

Optimiser son code en Java

Pavlos Kosmetatos

Lead Engineer @Wealthyhood

Exécution séquentielle vs parallèle

  • Traitement séquentiel -> les opérations s'exécutent l'une après l'autre
  • Traitement parallèle -> plusieurs opérations s'exécutent en même temps

Comment ?

  • Les CPU modernes ont plusieurs cœurs
  • Thread : plus petite unité d'exécution d'un programme
  • Le multithreading répartit le travail entre ces cœurs

Le monothreading, c'est une route à une voie où les voitures se suivent. Le multithreading, ce sont plusieurs voies où elles roulent en parallèle !

Optimiser son code en Java

Utiliser des threads

  • La classe Thread permet de créer de nouveaux chemins d'exécution
  • Chaque Thread peut s'exécuter indépendamment
Runnable task = () -> {
    System.out.println("Processing on thread: " + 
                       Thread.currentThread().getName());
};

Thread thread = new Thread(task);
thread.start();
Processing on thread: Thread-0
Optimiser son code en Java

Gérer plusieurs threads

List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
    Thread thread = new Thread(() -> System.out.println("Processing data on Thread-" + i));
    threads.add(thread);
    thread.start();
}

for (Thread t : threads) {
    t.join(); // Attend que tous les threads se terminent
}
// Processing data on Thread-0
// Processing data on Thread-2
// Processing data on Thread-1
// Processing data on Thread-3
Optimiser son code en Java

Streams parallèles

  • Streams : fonctionnalité Java 8+ pour un parallélisme simplifié
  • Gèrent automatiquement la création et la gestion des threads
  • Deux façons de créer :
    • collection.parallelStream()
    • Stream.of(...).parallel()
Optimiser son code en Java

Exemple de streams parallèles

// Traitement séquentiel
List<Integer> result1 = new ArrayList<>();
for (int i = 0; i < numbers.size(); i++) {
    result1.add(numbers.get(i) * 2);
}

// Traitement séquentiel avec stream List<Integer> result2 = numbers.stream() .map(n -> n * 2) .collect(Collectors.toList());
// Traitement parallèle avec parallel stream List<Integer> result3 = numbers.parallelStream() .map(n -> n * 2) .collect(Collectors.toList());
Optimiser son code en Java

Quand utiliser le traitement parallèle

  • Opérations intensives CPU
  • Traitements indépendants
  • Grandes collections de données
  • Nombre de cœurs CPU > 1
  • Le surcoût du parallélisme peut ne pas valoir le coup pour :
    • Petits jeux de données
    • Opérations simples
Optimiser son code en Java

Récapitulatif

  • Classe Thread pour créer des chemins d'exécution parallèles
  • Streams parallèles pour simplifier le traitement des collections
  • Les gains dépendent de :
    • Type de charge
    • Taille des données
    • Cœurs disponibles
Optimiser son code en Java

Passons à la pratique !

Optimiser son code en Java

Preparing Video For Download...