← Назад к вопросам

Для чего нужен Queue?

2.0 Middle🔥 121 комментариев
#Коллекции#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Queue: назначение и использование

Queue (очередь) — это структура данных, которая реализует принцип FIFO (First-In-First-Out). Она используется для упорядочивания обработки элементов в порядке их поступления, что критично для многих real-world приложений.

Основной принцип FIFO

// Queue работает по принципу FIFO
// Первый поступивший элемент — первый обработанный

Queue<String> queue = new LinkedList<>();

// Добавление (enqueue)
queue.add("first");   // Добавляем в конец
queue.add("second");
queue.add("third");

// Удаление/получение (dequeue)
String first = queue.poll();    // Удаляет из начала -> "first"
String second = queue.poll();   // -> "second"
String third = queue.poll();    // -> "third"

Интерфейс Queue

// Queue предоставляет два способа работы с элементами

// Способ 1: Методы, выбрасывающие исключения
Queue<Integer> queue1 = new LinkedList<>();

queue1.add(1);      // Добавить (выбросит исключение если очередь полна)
queue1.remove();    // Удалить (выбросит исключение если очередь пуста)
queue1.element();   // Получить без удаления (выбросит исключение если пуста)

// Способ 2: Методы, возвращающие null или false
Queue<Integer> queue2 = new LinkedList<>();

queue2.offer(1);    // Добавить (вернёт false если полна)
queue2.poll();      // Удалить (вернёт null если пуста)
queue2.peek();      // Получить (вернёт null если пуста)

Практическое применение

1. Обработка задач (Task Processing)

public class TaskProcessor {
    private Queue<Task> taskQueue = new LinkedList<>();
    
    public void submitTask(Task task) {
        taskQueue.offer(task); // Добавляем в очередь
    }
    
    public void processTasks() {
        while (!taskQueue.isEmpty()) {
            Task task = taskQueue.poll(); // Берём из очереди
            if (task != null) {
                task.execute();
            }
        }
    }
}

class Task {
    private String name;
    
    public Task(String name) {
        this.name = name;
    }
    
    public void execute() {
        System.out.println("Выполняю: " + name);
    }
}

// Использование
TaskProcessor processor = new TaskProcessor();
processor.submitTask(new Task("Отправить email"));
processor.submitTask(new Task("Сохранить файл"));
processor.submitTask(new Task("Обновить БД"));
processor.processTasks();

2. Буферизация между быстрым и медленным потребителем

public class ProducerConsumer {
    private BlockingQueue<Data> buffer = new LinkedBlockingQueue<>(100);
    
    // Быстрый производитель
    public void produce() {
        for (int i = 0; i < 1000; i++) {
            try {
                buffer.put(new Data(i)); // Блокирует если очередь полна
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    // Медленный потребитель
    public void consume() {
        for (int i = 0; i < 1000; i++) {
            try {
                Data data = buffer.take(); // Ждёт если очередь пуста
                slowProcess(data);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    private void slowProcess(Data data) {
        try { Thread.sleep(100); } catch (Exception e) {}
    }
}

3. Обработка запросов в веб-сервере

public class WebServer {
    private BlockingQueue<HttpRequest> requestQueue = 
        new LinkedBlockingQueue<>(1000);
    private ExecutorService workerThreads = 
        Executors.newFixedThreadPool(10);
    
    // Принимаем входящие запросы
    public void acceptRequest(HttpRequest request) {
        try {
            requestQueue.put(request); // Добавляем в очередь
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    // Worker потоки обрабатывают запросы по очереди
    public void start() {
        for (int i = 0; i < 10; i++) {
            workerThreads.submit(() -> {
                while (true) {
                    try {
                        HttpRequest request = requestQueue.take();
                        handleRequest(request);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
        }
    }
    
    private void handleRequest(HttpRequest request) {
        // Обработка запроса
    }
}

4. Message Queue для асинхронной обработки

// Имитация message broker (как RabbitMQ или Kafka)
public class SimpleMessageBroker {
    private BlockingQueue<Message> messageQueue = 
        new LinkedBlockingQueue<>();
    
    // Publisher отправляет сообщения
    public void publish(Message message) {
        try {
            messageQueue.put(message);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    // Subscriber получает сообщения
    public void subscribe(Consumer<Message> handler) {
        new Thread(() -> {
            while (true) {
                try {
                    Message message = messageQueue.take();
                    handler.accept(message);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

Типы Queue

1. LinkedList (unbounded)

Queue<String> queue = new LinkedList<>();
// Не имеет максимального размера
// Может расти неограниченно
// Медленнее чем ArrayDeque в большинстве операций

2. ArrayDeque (double-ended deque)

Queue<String> queue = new ArrayDeque<>();
// Более быстрая чем LinkedList
// Unbounded
// Может работать как Deque (добавление с обоих концов)

3. BlockingQueue (потокобезопасная)

// LinkedBlockingQueue
BlockingQueue<String> queue = new LinkedBlockingQueue<>(100);
queue.put("item");      // Блокирует если полна
queue.take();           // Блокирует если пуста

// ArrayBlockingQueue
BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);

// PriorityQueue (с приоритетами)
Queue<Task> queue = new PriorityQueue<>((t1, t2) -> 
    Integer.compare(t1.getPriority(), t2.getPriority())
);

Практический пример: Обработка уведомлений

public class NotificationService {
    private BlockingQueue<Notification> notificationQueue = 
        new LinkedBlockingQueue<>();
    
    // API получает уведомления
    public void scheduleNotification(Notification notification) {
        notificationQueue.offer(notification);
    }
    
    // Background поток отправляет уведомления
    public void start() {
        Thread sender = new Thread(() -> {
            while (true) {
                try {
                    Notification notification = notificationQueue.take();
                    sendNotification(notification);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        sender.setDaemon(true);
        sender.start();
    }
    
    private void sendNotification(Notification notification) {
        // Отправка email, SMS, push-уведомления и т.д.
        System.out.println("Отправляю: " + notification.getMessage());
    }
}

class Notification {
    private String message;
    private String recipient;
    
    public Notification(String message, String recipient) {
        this.message = message;
        this.recipient = recipient;
    }
    
    public String getMessage() { return message; }
    public String getRecipient() { return recipient; }
}

Преимущества Queue

  1. FIFO порядок — элементы обрабатываются в порядке поступления
  2. Decoupling — производитель и потребитель независимы
  3. Backpressure — BlockingQueue управляет нагрузкой
  4. Простота — интуитивный интерфейс
  5. Масштабируемость — легко добавить несколько потребителей

Когда использовать Queue

  • Асинхронная обработка задач
  • Балансировка нагрузки
  • Буферизация между компонентами
  • Очереди печати, почты, уведомлений
  • Message brokers (RabbitMQ, Kafka)
  • Thread pools и ExecutorService

Queue — это fundamental структура данных для построения масштабируемых и отзывчивых приложений.