7. Interfaces Queue et Deque

7.1. Notion de file d'attente

Une file d'attente est une collection normale (techniquement, l'interface Queue étend l'interface Collection), avec quelques différences sémantiques. L'utilisation classique d'une file d'attente, est de servir de tampon entre une source d'objets et un consommateur de ces mêmes objets. Traditionnellement, une file d'attente expose trois types de méthodes :
  • ajout d'un objet dans la file ;
  • examen de l'objet suivant disponible ;
  • consommation de l'objet suivant disponible, et retrait de la file.
À la différence des collections, les files d'attente ont une capacité limitée. Il se peut que l'ajout d'un objet dans une file d'attente échoue. Nous verrons alors que les files d'attente proposent différents comportements en cas d'échec d'un ajout : génération d'exception, ou retour d'un booléen à false. Traditionnellement, on définit deux types de files d'attente : FIFO (qui signifie first in first out), et LIFO ( last in, first out). La spécification de l'interface Queue nous indique qu'il est de la responsabilité de l'implémentation de définir quel type de fonctionnement elle adopte.

7.2. Détail des méthodes disponibles

7.2.1. Interface Queue

L'interface Queue, qui modélise une file d'attente simple, expose six méthodes, qui sont les suivantes.
  • add(T t) et offer(T t) permettent d'ajouter un élément à la liste. Si la capacité maximale de la liste est atteinte, alors add() jette une exception de type IllegalStateException, et offer() retourne false.
  • remove() et poll() retirent toutes les deux de cette file d'attente. Si aucun élément n'est disponible, alors remove() jette une exception de type NoSuchElementException, tandis que poll() retourne null.
  • element() et peek() examinent toutes les deux l'élément disponible, sans le retirer de la file d'attente. Si aucun élément n'est disponible, alors element() jette une exception de type NoSuchElementException, tandis que peek() retourne null.

7.2.2. Interface Deque

Cette interface est une extension de Queue, ajoutée en Java 6. Elle définit la notion de file d'attente à double extrémité : il est possible d'ajouter des éléments au début de la file ou à la fin, avec la même sémantique que pour Queue. Suivant la logique de la construction de Queue, Deque expose trois types de méthodes, qui permettent d'ajouter, de retirer, ou d'examiner l'élément suivant de la file. Chacune de ces méthodes existe en deux versions : la première agit sur une extrémité de la file, et la seconde sur l'autre. Chacune de ces méthodes existe encore en deux versions : la première jette une exception en cas d'échec, la seconde retourne false. Cela fait un total de douze méthodes, que l'on peut regrouper dans les tableaux suivants.

Tableau 1. Méthodes de Deque

Jette une exception Retourne false  
Insertion addFirst(T t) / addLast(T t) offerFirst(T t) / offerLast(T t)  
Retrait removeFirst(T t) / removeLast(T t) pollFirst(T t) / pollLast(T t)  
Examen getFirst(T t) / getLast(T t) peekFirst(T t) / peekLast(T t)  

L'interface Deque expose également les deux méthodes iterator() et descendingIterator(), qui permettent d'itérer dans les deux sens de la file d'attente. Enfin, elle expose deux méthodes removeFirst(Object) et removeLast(Object), qui permettent de retirer respectivement la première et la dernière occurrence de l'objet passé en paramètre.

7.3. Utilisation des interfaces Queue et Deque

Ces interfaces peuvent bien sûr être utilisées dans n'importe quel contexte. Cela dit, elles sont étendues dans l'API Concurrent par d'autres interfaces, qui portent le même nom, avec Blocking au milieu, et c'est dans ce domaine que leur importance est la plus grande. Nous verrons donc des exemples d'utilisation très précis dans ce contexte, dans le chapitre sur la programmation concurrente.
Java API avancées
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
API Collection
1. Introduction
2. Interface Collection
2.1. Notion de Collection
2.2. Détail des méthodes disponibles
2.3. Interface Iterator
2.4. Implémentation, exemples d'utilisation
3. Interface List
3.1. Notion de List
3.2. Détail des méthodes disponibles
3.3. Interface ListIterator
3.4. Implémentations, exemples d'utilisation
4. Interface Set
4.1. Notion de Set
4.2. Implémentations HashSet et LinkedHashSet
4.3. Exemples d'utilisation
5. Interface SortedSet
5.1. Notion de SortedSet
5.2. Détails des méthodes disponibles
5.3. Exemples d'utilisation
6. Interface NavigableSet
6.1. Notion de NavigableSet
6.2. Détails des méthodes disponibles
6.3. Exemple d'utilisation
7. Interfaces Queue et Deque
7.1. Notion de file d'attente
7.2. Détail des méthodes disponibles
7.3. Utilisation des interfaces Queue et Deque
8. Tables de hachage
8.1. Notion de table de hachage
8.2. Interface Map
8.3. Interface Map.Entry
8.4. Interface SortedMap
8.5. Interface NavigableMap
8.6. Implémentations
8.7. Exemples d'utilisation
9. Classes utilitaires Collections et Arrays
9.1. Introduction
9.2. Classe Arrays
9.3. Classe Collections
Génériques
1. Introduction
2. Un premier exemple
2.1. Une première classe générique
2.2. Une première méthode générique
3. Contraindre un type générique
3.1. Problème posé
3.2. Contraindre un type générique
4. Implémentation des génériques
4.1. Type erasure
4.2. Types génériques et casts
4.3. Type générique et exception
4.4. Construction d'une instance générique
4.5. Génériques et membres statiques
4.6. Collisions de méthodes génériques
4.7. Implémentation de plusieurs types identiques
5. Type <?>
5.1. Introduction
5.2. Type ? extension d'un type
5.3. Type ? super-type d'un type
Expressions régulières
1. Introduction
2. Mise en œuvre des expressions régulières
2.1. Fonctionnement d'une regexp
2.2. Fonctionnement de l'API en Java
2.3. Un premier exemple
2.4. Classe Pattern
2.5. Classe Matcher
2.6. Utilisation des méthode find() et group()
2.7. Méthodes de remplacement
2.8. Sélection de régions
3. Syntaxe des expressions régulières
3.1. Notion de classe
3.2. Étude d'un cas réel
3.3. Recherche d'un mot précis
3.4. Recherche de deux mots précis
3.5. Recherche d'un mot commençant par une lettre donnée
3.6. Cas de mots comportant des caractères accentués
3.7. Recherche sur les lignes
Introspection
1. Introduction
2. La classe Class
2.1. Utilisation de Class
2.2. Méthodes disponibles
2.3. Remarque sur la propriété Accessible
2.4. Type d'une classe
2.5. Création d'une instance à partir d'un objet Class
2.6. Cas des énumérations
3. Les classes Method et Constructor
3.1. Utilisation de Method
3.2. Utilisation de Constructor
3.3. Méthodes disponibles
3.4. Invocation d'une méthode par introspection
4. La classe Field
4.1. Utilisation de Field
4.2. Méthodes disponibles
4.3. Accès à un champ par introspection
5. La classe Modifier
Programmation concurrente
1. Introduction
2. Lançons nos premiers threads
2.1. Introduction
2.2. Un premier thread, extension de Thread
2.3. Un deuxième thread, implémentation de Runnable
2.4. Remarque sur la méthode Thread.sleep(long)
2.5. Arrêter un thread
3. Concurrence d'accès
3.1. Notion d'état
3.2. Exemple de concurrence d'accès sur un état
3.3. Analyse de la concurrence d'accès
3.4. Solution au problème
3.5. Champs volatile
4. Synchronisation
4.1. Définition d'un bloc synchronisé
4.2. Fonctionnement d'un bloc synchronisé
4.3. Notion de deadlock
4.4. Bonnes pratiques pour la synchronisation de threads
5. Opérations atomiques
5.1. Atomicité d'une opération
5.2. Solutions disponibles
5.3. Variables atomiques
6. Collections synchronisées et concurrentes
6.1. Introduction
6.2. Position du problème
6.3. Solutions proposées
7. Files d'attente
7.1. Introduction, pattern producteur / consommateur
7.2. Interface BlockingQueue<E>
7.3. Implémentations de BlockingQueue
7.4. Exemple de producteur / consommateur
7.5. Arrêter un producteur / consommateur : pilule empoisonnée
8. Classes utilitaires de l'API Concurrent
8.1. Introduction
8.2. Énumération TimeUnit
8.3. Interface Callable<V>
8.4. Interfaces Future<V> et RunnableFuture<V>
8.5. Interface ScheduledFuture<V> et RunnableScheduledFuture<V>
9. Pattern executor
9.1. Notion de réserve de threads
9.2. Interface Executor
9.3. Interface ExecutorService
9.4. Interface ScheduledExecutorService
9.5. Classe Executors
9.6. Pattern de lancement de tâches
10. Classes de contrôle d'accès
10.1. Introduction
10.2. Interfaces Lock et ReadWriteLock
10.3. Notion de verrou réentrant
10.4. Classe RentrantLock
10.5. Classe ReadWriteRentrantLock
11. Sémaphores, barrières et latches
11.1. Introduction
11.2. Notion de sémaphore, classe Semaphore
11.3. Notion de latch, classe CountDownLatch
11.4. Notion de barrière, classe CyclicBarrier