Очереди задач в Java для начинающих: простое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: что такое очередь задач в Java и зачем она нужна

В программировании часто возникает необходимость обрабатывать данные в порядке их поступления. Представьте себе очередь в кассу супермаркета: первый пришедший обслуживается первым. В Java эту логику реализует интерфейс Queue и его реализации. Очередь задач (Task Queue) — это структура данных, которая работает по принципу FIFO (First In, First Out — «первым пришёл, первым ушёл»).

Зачем это нужно? Очереди незаменимы при:

  • Обработке запросов на сервере (веб-сервер, API)
  • Буферизации данных перед записью в базу
  • Реализации пула потоков (Thread Pool)
  • Организации асинхронных задач

В этой статье мы разберём основные интерфейсы и классы для работы с очередями в Java, напишем простые примеры и дадим практические советы. Материал рассчитан на новичков, поэтому мы начнём с самых основ.

1. Интерфейс Queue и его базовые методы

В Java интерфейс java.util.Queue определяет основные операции для работы с очередью. Главные методы:

  • add(E e) — добавляет элемент в конец очереди. Если очередь заполнена, выбрасывает исключение.
  • offer(E e) — добавляет элемент. В отличие от add(), возвращает false при неудаче, а не исключение.
  • remove() — удаляет и возвращает первый элемент. Если очередь пуста — исключение NoSuchElementException.
  • poll() — удаляет и возвращает первый элемент, или null если очередь пуста.
  • element() — возвращает первый элемент без удаления. Исключение при пустой очереди.
  • peek() — возвращает первый элемент без удаления, или null.

Самая популярная реализация Queue — это LinkedList. Она проста и подходит для большинства базовых задач.

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        // Создаём очередь строк
        Queue<String> taskQueue = new LinkedList<>();

        // Добавляем задачи (метод offer)
        taskQueue.offer("Задача 1: Обработать заказ");
        taskQueue.offer("Задача 2: Отправить email");
        taskQueue.offer("Задача 3: Сформировать отчёт");

        System.out.println("Очередь задач: " + taskQueue);

        // Обрабатываем задачи по очереди
        while (!taskQueue.isEmpty()) {
            String task = taskQueue.poll(); // Берём первую задачу
            System.out.println("Выполняется: " + task);
            // Здесь можно написать логику выполнения
        }

        System.out.println("Все задачи выполнены. Очередь пуста: " + taskQueue.isEmpty());
    }
}

Вывод программы:

Очередь задач: [Задача 1: Обработать заказ, Задача 2: Отправить email, Задача 3: Сформировать отчёт]
Выполняется: Задача 1: Обработать заказ
Выполняется: Задача 2: Отправить email
Выполняется: Задача 3: Сформировать отчёт
Все задачи выполнены. Очередь пуста: true

2. Deque — двунаправленная очередь

Интерфейс Deque (Double Ended Queue) расширяет Queue и позволяет работать с обоими концами очереди. Вы можете добавлять и удалять элементы как с начала, так и с конца. Это даёт больше гибкости.

Основные дополнительные методы:

  • addFirst() / offerFirst() — добавить в начало.
  • addLast() / offerLast() — добавить в конец (аналог offer()).
  • removeFirst() / pollFirst() — удалить из начала.
  • removeLast() / pollLast() — удалить из конца.
  • getFirst() / peekFirst() — посмотреть первый элемент.
  • getLast() / peekLast() — посмотреть последний элемент.

Реализации: ArrayDeque (быстрее, чем LinkedList) и LinkedList.

import java.util.Deque;
import java.util.ArrayDeque;

public class DequeExample {
    public static void main(String[] args) {
        Deque<String> deque = new ArrayDeque<>();

        // Добавляем задачи в конец (как обычная очередь)
        deque.offerLast("Задача A");
        deque.offerLast("Задача B");

        // Добавляем срочную задачу в начало
        deque.offerFirst("Срочная задача!");

        System.out.println("Текущая очередь: " + deque);

        // Обрабатываем сначала срочную задачу
        String urgentTask = deque.pollFirst();
        System.out.println("Срочная: " + urgentTask);

        // Затем остальные
        String task = deque.pollFirst();
        System.out.println("Обычная: " + task);

        System.out.println("Оставшиеся: " + deque);
    }
}

Вывод:

Текущая очередь: [Срочная задача!, Задача A, Задача B]
Срочная: Срочная задача!
Обычная: Задача A
Оставшиеся: [Задача B]

3. PriorityQueue — очередь с приоритетами

Иногда задачи нужно обрабатывать не в порядке поступления, а по их важности. Например, сначала обработать VIP-заказы, а потом обычные. Для этого существует PriorityQueue. Она автоматически сортирует элементы согласно заданному компаратору или естественному порядку (если элементы реализуют Comparable).

Важно: PriorityQueue не гарантирует порядок элементов при итерации, но гарантирует, что при вызове poll() будет возвращён элемент с наивысшим приоритетом (наименьший в случае естественного порядка).

import java.util.PriorityQueue;
import java.util.Queue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // Очередь с приоритетом (числа — меньший приоритет = выше)
        Queue<Integer> priorityQueue = new PriorityQueue<>();

        priorityQueue.offer(5);
        priorityQueue.offer(1);
        priorityQueue.offer(3);
        priorityQueue.offer(2);

        System.out.println("Очередь: " + priorityQueue); // Порядок может быть любым

        // Извлекаем элементы — всегда наименьший
        while (!priorityQueue.isEmpty()) {
            System.out.println("Из                

Блоги

Рекомендаций по книгам