Java - Planificateur de Thread
Bonjour à tous, futurs sorciers Java ! Aujourd'hui, nous allons entreprendre un voyage passionnant dans le monde de la planification des threads Java. Ne vous inquiétez pas si vous êtes nouveau en programmation – je serai votre guide ami, et nous aborderons ce sujet étape par étape. Alors, prenez vos baguettes virtuelles (claviers), et plongeons-y !
Qu'est-ce que la Planification des Threads ?
Avant de plonger dans les détails, comprenons ce qu'est la planification des threads. Imaginez que vous êtes un maître de cérémonie de cirque (cela serait le temps d'exécution Java), et que vous avez plusieurs artistes (threads) en attente pour montrer leurs numéros. Votre travail consiste à décider quel artiste va sur scène et pendant combien de temps. C'est essentiellement ce que fait la planification des threads dans Java – elle gère plusieurs threads et décide lequel doit s'exécuter et quand.
Pourquoi avons-nous besoin de Planification des Threads ?
Vous pourriez vous demander, "Pourquoi ne pouvons-nous pas laisser tous les threads s'exécuter quand ils veulent ?" Eh bien, imaginez si tous les artistes de cirque essayaient de performer en même temps – ce serait le chaos ! La planification des threads aide à maintenir l'ordre, assure une allocation équitable des ressources et améliore la performance globale du système.
Planificateur de Thread de Java
Java a un planificateur de thread intégré qui s'occupe de cette tâche complexe pour nous. Il utilise une combinaison de planification au niveau du système d'exploitation et de ses propres algorithmes pour gérer les threads efficacement.
États des Threads
Avant de nous plonger dans la planification, examinons rapidement les différents états dans lesquels peut se trouver un thread :
- Nouveau
- Exécutable
- En cours d'exécution
- Bloqué/En attente
- Terminé
Le planificateur est responsable du déplacement des threads entre ces états.
Création et Planification de Threads de Base
Commençons par un exemple simple pour voir comment Java crée et planifie des threads :
public class SimpleThreadExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 1: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 2: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}
}
Dans cet exemple, nous créons deux threads qui impriment des nombres de 0 à 4. L'appel Thread.sleep(1000)
fait pause chaque thread pendant 1 seconde entre les impressions.
Lorsque vous exécutez ce programme, vous remarquerez que la sortie peut ne pas être dans un ordre alternatif parfait. C'est parce que le planificateur Java décide quand basculer entre les threads !
Priorités des Threads
Java nous permet de donner des indices au planificateur sur les threads les plus importants. Nous pouvons définir les priorités des threads à l'aide de la méthode setPriority()
. Modifions notre exemple précédent :
public class ThreadPriorityExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread de Priorité Basse: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread de Priorité Haute: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.setPriority(Thread.MIN_PRIORITY);
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
Dans cet exemple, nous définissons thread1
avec la priorité la plus basse et thread2
avec la priorité la plus haute. Bien que cela ne garantisse pas que thread2
s'exécutera toujours en premier ou plus souvent, cela donne au planificateur un indice qu'il devrait préférer thread2
lorsque cela est possible.
ScheduledExecutorService
Maintenant, examinons une manière plus avancée de planifier des threads à l'aide de ScheduledExecutorService
. Cet outil puissant nous permet de planifier des tâches pour s'exécuter après un délai ou à des intervalles fixes.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorExample {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
Runnable task1 = () -> System.out.println("Tâche 1 exécutée à : " + System.currentTimeMillis());
Runnable task2 = () -> System.out.println("Tâche 2 exécutée à : " + System.currentTimeMillis());
executor.schedule(task1, 5, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(task2, 0, 2, TimeUnit.SECONDS);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
Dans cet exemple :
- Nous créons un
ScheduledExecutorService
avec 2 threads. -
task1
est planifiée pour s'exécuter une fois après un délai de 5 secondes. -
task2
est planifiée pour s'exécuter toutes les 2 secondes, en commençant immédiatement. - Nous laissons le programme s'exécuter pendant 10 secondes avant de fermer l'executor.
Cela montre comment nous pouvons contrôler précisément quand et combien de fois nos tâches s'exécutent.
Méthodes de ScheduledExecutorService
Voici un tableau des principales méthodes fournies par ScheduledExecutorService
:
Méthode | Description |
---|---|
schedule(Runnable, long, TimeUnit) |
Planifie une tâche unique pour s'exécuter après un délai spécifié |
scheduleAtFixedRate(Runnable, long, long, TimeUnit) |
Planifie une tâche pour s'exécuter périodiquement, avec un délai fixe entre le début de chaque exécution |
scheduleWithFixedDelay(Runnable, long, long, TimeUnit) |
Planifie une tâche pour s'exécuter périodiquement, avec un délai fixe entre la fin d'une exécution et le début de la suivante |
Conclusion
Et voilà, les amis ! Nous avons traversé les bases de la planification des threads Java, de la création simple de threads à la planification avancée avec ScheduledExecutorService
. Rappelez-vous, la planification des threads est comme diriger un orchestre – c'est tout une question de harmony et de timing.
À mesure que vous continuez votre aventure Java, vous découvrirez encore plus de moyens pour affiner le comportement des threads. Mais pour l'instant, félicitez-vous – vous avez fait un grand pas dans le monde de la programmation concurrente !
Continuez à pratiquer, restez curieux, et surtout, amusez-vous à coder ! Qui sait, peut-être que vous écrirez un jour la prochaine génération de planificateurs de threads Java. En attendant, bonne threading !
Credits: Image by storyset