λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

빈 ꡬ멍 μ±„μš°κΈ°

[Java] Queue μΈν„°νŽ˜μ΄μŠ€

좜처

ChatGPT


Queue μΈν„°νŽ˜μ΄μŠ€λŠ” μžλ°” μ»¬λ ‰μ…˜ ν”„λ ˆμž„μ›Œν¬μ—μ„œ FIFO(First-In-First-Out) 원칙에 따라 μš”μ†Œλ₯Ό μ²˜λ¦¬ν•˜λŠ” 자료ꡬ쑰λ₯Ό μ •μ˜ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ΄λ‹€. 큐가 λ¨Όμ € μΆ”κ°€λœ μš”μ†Œκ°€ λ¨Όμ € μ œκ±°λ˜λŠ” ꡬ쑰λ₯Ό λ”°λ₯΄λ©°, 주둜 μž‘μ—… κ΄€λ¦¬λ‚˜ λ©”μ‹œμ§€ μ²˜λ¦¬μ™€ 같은 λŒ€κΈ°μ—΄μ„ μ²˜λ¦¬ν•  λ•Œ μ‚¬μš©λœλ‹€.

 

Queue μΈν„°νŽ˜μ΄μŠ€λŠ” μ»¬λ ‰μ…˜(Collection) μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒμ†ν•˜λ©°, 큐 자료ꡬ쑰의 νŠΉν™”λœ λ©”μ†Œλ“œλ“€μ„ μ •μ˜ν•œλ‹€.

 

1. Queue μΈν„°νŽ˜μ΄μŠ€μ˜ μ£Όμš” νŠΉμ§•

FIFO μˆœμ„œ

Queue λŠ” FIFO(First-In-First-Out) λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€. 즉, 큐에 λ¨Όμ € μ‚½μž…λœ μš”μ†Œκ°€ λ¨Όμ € 처리되고 μ œκ±°λœλ‹€.

null ν—ˆμš© μ•ˆ 함

λŒ€λΆ€λΆ„μ˜ 큐 κ΅¬ν˜„μ²΄λŠ” null 값을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λŠ” null이 큐의 끝을 λ‚˜νƒ€λ‚΄κ±°λ‚˜ νŠΉλ³„ν•œ 의미λ₯Ό κ°€μ§ˆ 수 있기 λ•Œλ¬Έμ— μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

동기화 지원

Queue μΈν„°νŽ˜μ΄μŠ€λŠ” λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ λ™μ‹œ 접근을 μ•ˆμ „ν•˜κ²Œ μ²˜λ¦¬ν•  수 μžˆλŠ” 동기화 큐 κ΅¬ν˜„μ—(ConcurrentLinkedQueue, BlockingQueue λ“±)λ₯Ό μ œκ³΅ν•œλ‹€.

2. Queue μΈν„°νŽ˜μ΄μŠ€μ˜ μ£Όμš” λ©”μ†Œλ“œ

Queue μΈν„°νŽ˜μ΄μŠ€λŠ” μš”μ†Œλ₯Ό μ‚½μž…, 제거, μ‘°νšŒν•˜λŠ” λ©”μ†Œλ“œλ“€μ„ μ œκ³΅ν•˜λ©°, 각 μž‘μ—…μ— λŒ€ν•΄ 두 가지 λ³€ν˜•μ„ μ œκ³΅ν•œλ‹€.

  • μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” λ©”μ†Œλ“œ
  • null λ˜λŠ” falseλ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ†Œλ“œ

1. μ‚½μž… κ΄€λ ¨ λ©”μ†Œλ“œ

boolean add(E e)

큐의 맨 뒀에 μš”μ†Œλ₯Ό μ‚½μž…ν•œλ‹€. 큐의 크기 μ œν•œμ„ μ΄ˆκ³Όν•  경우 μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€.

boolean offer(E e)

큐의 맨 뒀에 μš”μ†Œλ₯Ό μ‚½μž…ν•œλ‹€. 큐가 가득 μ°¬ 경우 falseλ₯Ό λ°˜ν™˜ν•˜λ©°, μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.

2. 제거 κ΄€λ ¨ λ©”μ†Œλ“œ

E remove()

큐의 첫 번째 μš”μ†Œλ₯Ό μ œκ±°ν•˜κ³  λ°˜ν™˜ν•œλ‹€. 큐가 λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€.

E poll()

큐의 첫 번째 μš”μ†Œλ₯Ό μ œκ±°ν•˜κ³  λ°˜ν™˜ν•œλ‹€. 큐가 λΉ„μ–΄ 있으면 null을 λ°˜ν™˜ν•œλ‹€.

3. 쑰회 κ΄€λ ¨ λ©”μ†Œλ“œ

E element()

큐의 첫 번째 μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜λ˜, μ œκ±°ν•˜μ§€ μ•ŠλŠ”λ‹€. 큐가 λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€. 

E peek()

큐의 첫 번째 μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜λ˜, μ œκ±°ν•˜μ§€ μ•ŠλŠ”λ‹€. 큐가 λΉ„μ–΄ 있으면 null을 λ°˜ν™˜ν•œλ‹€.

 

3. Queue μΈν„°νŽ˜μ΄μŠ€ λ©”μ†Œλ“œ λ™μž‘ 비ꡐ

λ©”μ†Œλ“œ 성곡 μ‹œ λ™μž‘ μ‹€νŒ¨ μ‹œ λ™μž‘
add(e) μš”μ†Œλ₯Ό 큐에 μ‚½μž… μ˜ˆμ™Έ(IllegalStateException) λ°œμƒ
offer(e) μš”μ†Œλ₯Ό 큐에 μ‚½μž… false λ°˜ν™˜
remove() 첫 번째 μš”μ†Œ 제거 및 λ°˜ν™˜ μ˜ˆμ™Έ(NoSuchElementException) λ°œμƒ
poll() 첫 번째 μš”μ†Œ 제거 및 λ°˜ν™˜ null λ°˜ν™˜
element() 첫 번째 μš”μ†Œ 쑰회 μ˜ˆμ™Έ(NoSuchElementException) λ°œμƒ
peek() 첫 번째 μš”μ†Œ 쑰회 null λ°˜ν™˜

 

4. Queue μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„ 클래슀

Queue μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ μ£Όμš” ν΄λž˜μŠ€λ“€μ€ 각기 λ‹€λ₯Έ νŠΉμ„±κ³Ό μš©λ„λ₯Ό 가지며, λ‹€μ–‘ν•œ μƒν™©μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

LinkedList

μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 일반적인 μ—°κ²° 리슀트 기반 큐둜, null 값을 ν—ˆμš©ν•œλ‹€. 크기에 μ œν•œμ΄ μ—†μœΌλ©°, 큐 외에도 리슀트둜 μ‚¬μš©ν•  수 μžˆλ‹€.

PriorityQueue

μš°μ„ μˆœμœ„ 큐둜, μ‚½μž…λœ μš”μ†Œλ“€μ΄ μš°μ„ μˆœμœ„μ— 따라 μ •λ ¬λ˜λ©°, FIFO κ·œμΉ™ λŒ€μ‹  μœ μ„ μˆœμœ„ κ·œμΉ™μ„ λ”°λ₯Έλ‹€. 기본적으둜 μ΅œμ†Œ νž™μ„ μ‚¬μš©ν•΄ μš°μ„ μˆœμœ„λ₯Ό κ΄€λ¦¬ν•œλ‹€.

ArrayDeque

λ°°μ—΄ 기반의 큐둜, μ–‘μͺ½μ—μ„œ μ‚½μž…κ³Ό μ‚­μ œκ°€ κ°€λŠ₯ν•œ Deque(Double-Ended Queue)λ₯Ό κ΅¬ν˜„ν•œλ‹€. μŠ€νƒκ³Ό 큐의 λ™μž‘μ„ λͺ¨λ‘ μ§€μ›ν•œλ‹€.

ConcurrentLinkedQueue

비동기전(μŠ€λ ˆλ“œ μ•ˆμ „)으둜 λ™μž‘ν•˜λŠ” μ—°κ²° 리슀트 기반 큐둀, λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ μ‚¬μš©λœλ‹€.

BlockingQueue

λΈ”λ‘œν‚Ή 큐둜, μƒμ‚°μž-μ†ŒλΉ„μž νŒ¨ν„΄μ—μ„œ 주둜 μ‚¬μš©λ˜λ©°, 큐가 λΉ„μ–΄ 있으면 μš”μ†Œκ°€ 좔가될 λ•ŒκΉŒμ§€ 기닀리고, 큐가 가득 μ°¨λ©΄ 곡간이 생길 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” λ™μž‘μ„ ν•œλ‹€. μ£Όμš” κ΅¬ν˜„μ²΄λ‘œλŠ” ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue 등이 μžˆλ‹€.

 

5. Queue μ˜ˆμ‹œ

1. LinkedListλ₯Ό μ΄μš©ν•œ κΈ°λ³Έ 큐 κ΅¬ν˜„

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

public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        
        // 큐에 μš”μ†Œ μ‚½μž…
        queue.offer("apple");
        queue.offer("banana");
        queue.offer("cherry");

        // 큐의 첫 번째 μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜κ³  제거
        System.out.println("Poll: " + queue.poll());  // 좜λ ₯: apple

        // 큐의 첫 번째 μš”μ†Œλ₯Ό 쑰회 (μ œκ±°ν•˜μ§€ μ•ŠμŒ)
        System.out.println("Peek: " + queue.peek());  // 좜λ ₯: banana

        // νμ—μ„œ μš”μ†Œλ₯Ό 제거
        System.out.println("Remove: " + queue.remove());  // 좜λ ₯: banana

        // 남은 μš”μ†Œλ“€ 좜λ ₯
        System.out.println("Remaining Queue: " + queue);  // 좜λ ₯: [cherry]
    }
}

 

2. PriorityQueueλ₯Ό μ΄μš©ν•œ μš°μ„ μˆœμœ„ 큐

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

public class PriorityQueueExample {
    public static void main(String[] args) {
        Queue<Integer> priorityQueue = new PriorityQueue<>();
        
        // μš°μ„ μˆœμœ„ 큐에 μš”μ†Œ μ‚½μž… (기본적으둜 μ˜€λ¦„μ°¨μˆœ μ •λ ¬)
        priorityQueue.offer(40);
        priorityQueue.offer(10);
        priorityQueue.offer(30);
        priorityQueue.offer(20);

        // μš°μ„ μˆœμœ„κ°€ κ°€μž₯ 높은 μš”μ†Œλ₯Ό λ°˜ν™˜ν•˜κ³  제거
        System.out.println("Poll: " + priorityQueue.poll());  // 좜λ ₯: 10

        // 큐의 첫 번째 μš”μ†Œλ₯Ό 쑰회 (μ œκ±°ν•˜μ§€ μ•ŠμŒ)
        System.out.println("Peek: " + priorityQueue.peek());  // 좜λ ₯: 20

        // 남은 μš”μ†Œλ“€ 좜λ ₯
        System.out.println("Remaining Queue: " + priorityQueue);  // 좜λ ₯: [20, 40, 30]
    }
}

 

3. ArrayDequeλ₯Ό μ΄μš©ν•œ 큐와 μŠ€νƒ λ™μž‘

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

public class ArrayDequeExample {
    public static void main(String[] args) {
        Deque<String> deque = new ArrayDeque<>();
        
        // 큐처럼 λ™μž‘ (FIFO)
        deque.offer("apple");
        deque.offer("banana");
        deque.offer("cherry");

        System.out.println("Queue Poll: " + deque.poll());  // 좜λ ₯: apple
        System.out.println("Queue Remaining: " + deque);    // 좜λ ₯: [banana, cherry]

        // μŠ€νƒμ²˜λŸΌ λ™μž‘ (LIFO)
        deque.push("date");
        System.out.println("Stack Pop: " + deque.pop());    // 좜λ ₯: date
        System.out.println("Stack Remaining: " + deque);    // 좜λ ₯: [banana, cherry]
    }
}

 

6. BlockingQueue μ˜ˆμ‹œ (μƒμ‚°μž-μ†ŒλΉ„μž νŒ¨ν„΄)

BlockingQueueλŠ” μƒμ‚°μž-μ†ŒλΉ„μž(Producer-Consumer) νŒ¨ν„΄μ—μ„œ 주둜 μ‚¬μš©λœλ‹€. 큐가 λΉ„μ–΄ 있으면 μ†ŒλΉ„μžλŠ” 기닀리고, 큐가 가득 μ°¨λ©΄ μƒμ‚°μžλŠ” κΈ°λ‹€λ¦¬λŠ” λ™μž‘μ„ μˆ˜ν–‰ν•œλ‹€.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(2);

        // μƒμ‚°μž μŠ€λ ˆλ“œ
        new Thread(() -> {
            try {
                blockingQueue.put(1);
                System.out.println("Produced: 1");
                blockingQueue.put(2);
                System.out.println("Produced: 2");
                blockingQueue.put(3);  // 이 μ‹œμ μ—μ„œ λΈ”λ‘œν‚Ήλ¨ (큐가 가득 μ°ΌκΈ° λ•Œλ¬Έ)
                System.out.println("Produced: 3");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();

        // μ†ŒλΉ„μž μŠ€λ ˆλ“œ
        new Thread(() -> {
            try {
                Thread.sleep(2000);  // μž μ‹œ λŒ€κΈ° ν›„ μ†ŒλΉ„ μ‹œμž‘
                System.out.println("Consumed: " + blockingQueue.take());
                System.out.println("Consumed: " + blockingQueue.take());
                System.out.println("Consumed: " + blockingQueue.take());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}

 

이 μ˜ˆμ‹œμ—μ„œλŠ” μƒμ‚°μžκ°€ 큐에 μš”μ†Œλ₯Ό μ‚½μž…ν•˜κ³ , 큐가 가득 μ°¨λ©΄ λ‹€μŒ μš”μ†Œλ₯Ό μ‚½μž…ν•˜κΈ° μœ„ν•΄ λ‹€κΈ°ν•œλ‹€. μ†ŒλΉ„μžλŠ” 일정 μ‹œκ°„μ΄ μ§€λ‚œ ν›„ νμ—μ„œ μš”μ†Œλ₯Ό κΊΌλ‚΄κ³ , 큐가 λΉ„μ–΄ 있으면 λ‹€μŒ μš”μ†Œκ°€ 올 λ•Œκ°€μ§€ λŒ€κΈ°ν•œλ‹€.

 

7. Queue μΈν„°νŽ˜μ΄μŠ€μ˜ μš©λ„

μž‘μ—… λŒ€κΈ°μ—΄

μ—¬λŸ¬ μž‘μ—…μ„ μ°¨λ‘€λŒ€λ‘œ μ²˜λ¦¬ν•΄μ•Ό ν•  λŒ€ 큐λ₯Ό μ‚¬μš©ν•΄ μž‘μ—…μ„ μ €μž₯ν•˜κ³ , 처리 μ™„λ£Œ ν›„ νμ—μ„œ μ œκ±°ν•˜λŠ” λ°©μ‹μœΌλ‘œ ν™œμš©λ  수 μžˆλ‹€.

λ©”μ‹œμ§€ 처리 μ‹œμŠ€ν…œ

λ©”μ‹œμ§€ 큐 μ‹œμŠ€ν…œμ—μ„œ λ©”μ‹œμ§€λ₯Ό μ°¨λ‘€λŒ€λ‘œ μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ 자료ꡬ쑰둜 μ‚¬μš©λœλ‹€.

λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½

BlockingQueueλŠ” λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ μ•ˆμ „ν•˜κ²Œ 데이터λ₯Ό κ΅ν™˜ν•  수 μžˆλŠ” 큐λ₯Ό μ œκ³΅ν•΄, μƒμ‚°μž-μ†ŒλΉ„μž νŒ¨ν„΄μ— μ ν•©ν•˜λ‹€.

 

κ²°λ‘ 

Queue μΈν„°νŽ˜μ΄μŠ€λŠ” μžλ°”μ—μ„œ FIFO λ°©μ‹μ˜ 큐λ₯Ό κ΅¬ν˜„ν•˜λŠ” 데 μ‚¬μš©λ˜λ©°, λ‹€μ–‘ν•œ κ΅¬ν˜„μ²΄κ°€ μžˆμ–΄ 각기 λ‹€λ₯Έ νŠΉμ„±μ— 맞게 μ‚¬μš©ν•  수 μžˆλ‹€. μš°μ„ μˆœμœ„ 큐, 동기화 큐, λΈ”λ‘œν‚Ή 큐 λ“± λ‹€μ–‘ν•œ 상황에 λ§žλŠ” κ΅¬ν˜„μ²΄λ“€μ΄ μ œκ³΅λ˜μ–΄, λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œλ„ μ•ˆμ „ν•˜κ³  효율적으둜 데이터λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ‹€.