Files d'attente de tâches en Java : transformer le chaos en ordre

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Quand votre code commence à bégayer : introduction aux files d'attente et tâches en arrière-plan en Java

\n\n

Imaginez la situation : vous lancez un serveur web en Java. Un utilisateur envoie une requête — il faut envoyer un email, générer un rapport PDF et mettre à jour les statistiques. Si vous exécutez tout de manière synchrone, l'utilisateur attendra 30 secondes. Son café refroidira, et il ira chez vos concurrents. Cela vous dit quelque chose ?

\n\n

Dans le monde des tâches en arrière-plan Java, cela se résout élégamment : nous plaçons la tâche dans une file d'attente et renvoyons un « 200 OK » à l'utilisateur. Ensuite, en arrière-plan, notre worker traite tranquillement les emails, les PDF et les statistiques. Pas de chaos, seulement de l'ordre.

\n\n

Aujourd'hui, nous allons voir comment implémenter des files d'attente de tâches en Java — de la version monothread la plus simple aux solutions industrielles avec RabbitMQ et Kafka. Vous apprendrez à arrêter d'éteindre des incendies et à commencer à concevoir des systèmes fiables.

\n\n

Pourquoi utiliser des files d'attente ? Trois raisons qui vont vous surprendre

\n\n
    \n
  1. Asynchronisme — l'utilisateur n'attend pas. Le temps de réponse du serveur passe de 30 secondes à 5 millisecondes.
  2. \n
  3. Équilibrage de charge — les pics de requêtes ne font pas planter le serveur. Les tâches sont stockées dans la file d'attente et traitées au fur et à mesure que les ressources se libèrent.
  4. \n
  5. Tolérance aux pannes — si un worker tombe, la tâche reste dans la file d'attente. Un autre worker la reprend. Les données ne sont pas perdues.
  6. \n
\n\n

En Java, il existe des outils intégrés (ExecutorService, BlockingQueue) et des courtiers externes (RabbitMQ, Kafka). Le choix dépend de l'échelle. Commençons par le plus simple.

\n\n

File d'attente simple en Java : ExecutorService et BlockingQueue

\n\n

Si vous n'avez pas besoin d'un système distribué, mais simplement de déléguer un travail lourd en arrière-plan — utilisez ThreadPoolExecutor. C'est un pool de threads intégré qui récupère les tâches depuis une file d'attente.

\n\n

Exemple : pool de threads pour le traitement de commandes

\n\n
import java.util.concurrent.*;\n\npublic class OrderProcessor {\n    private final ExecutorService executor;\n\n    public OrderProcessor(int threadCount) {\n        // Création d'un pool avec un nombre fixe de threads\n        this.executor = Executors.newFixedThreadPool(threadCount);\n    }\n\n    public void processOrder(Order order) {\n        executor.submit(() -> {\n            // Travail lourd : génération du ticket, envoi d'email, mise à jour du stock\n            System.out.println("Traitement de la commande : " + order.getId());\n            try {\n                Thread.sleep(2000); // simulation du travail\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n            }\n            System.out.println("Commande " + order.getId() + " traitée");\n        });\n    }\n\n    public void shutdown() {\n        executor.shutdown();\n    }\n\n    public static void main(String[] args) {\n        OrderProcessor processor = new OrderProcessor(4);\n        for (int i = 0; i < 10; i++) {\n            processor.processOrder(new Order(i));\n        }\n        processor.shutdown();\n    }\n}\n\nclass Order {\n    private final int id;\n    public Order(int id) { this.id = id; }\n    public int getId() { return id; }\n}
\n\n

Que se passe-t-il ici ? Nous avons créé un pool de 4 threads. 10 commandes seront traitées par lots de 4 en parallèle. La file d'attente de tâches en Java est gérée en interne par ThreadPoolExecutor — il s'agit par défaut d'une LinkedBlockingQueue. Lorsque tous les threads sont occupés, les tâches attendent leur tour.

\n\n

Configuration avancée : priorités et tolérance aux pannes

\n\n

Et si certaines tâches sont urgentes ? Utilisez PriorityBlockingQueue :

\n\n
BlockingQueue<Runnable> priorityQueue = new PriorityBlockingQueue<>(\n    10,\n    Comparator.comparingInt(task -> ((PriorityTask) task).getPriority())\n);\n\nThreadPoolExecutor executor = new ThreadPoolExecutor(\n    2, 4, 60, TimeUnit.SECONDS, priorityQueue\n);
\n\n

Désormais, les tâches à haute priorité

Blogs

Book Recommendations