Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby에서 큐(Queue)를 사용하는 방법 완벽 가이드

Ruby에서 큐(Queue)란 무엇인가?

큐(queue)는 쉽게 말해 대기 목록입니다.

최신 애플 제품을 구매하기 위해 줄을 서 있는 모습, 영화 티켓을 끊기 위해 기다리는 모습, 마트 계산대에서 차례를 기다리는 상황을 떠올려 보세요.

이것이 바로 큐입니다!

그리고 이러한 큐는 Ruby 프로젝트에서도 충분히 활용할 수 있습니다.

큐는 언제 유용할까?

큐는 도착한 순서대로 작업을 처리할 수 있게 해줍니다. 따라서 오래 기다린 항목일수록 우선순위를 받아야 하는 모든 상황에 적합합니다.

대표적인 활용 사례는 다음과 같습니다:

  • 실제 세계의 대기열을 소프트웨어로 모델링
  • 너비 우선 탐색(BFS)과 같은 알고리즘 구현
  • CPU, 디스크, 프린터 등 공유 자원에 대한 접근 제어

자, 이제 코드를 살펴보겠습니다!

Ruby에서 큐 구현하기: 배열 활용

적절한 메서드만 사용한다면 일반 배열도 Queue처럼 동작하게 만들 수 있습니다.

핵심 메서드는 두 가지입니다:

  • unshift (Ruby 2.5 이상에서는 prepend)
  • pop

unshift를 호출하면 큐에 항목 하나를 추가합니다.

예제:

queue = []

queue.unshift "apple"
queue.unshift "orange"
queue.unshift "banana"

# ["banana", "orange", "apple"]

pop을 호출하면 큐에서 가장 먼저 들어온 항목이 제거됩니다. 이 항목이 바로 다음으로 처리해야 할 대상입니다.

예제:

queue.pop
# "apple"

queue.pop
# "orange"

항목을 제거하지 않고 다음 차례가 무엇인지 확인만 하고 싶다면 마지막 요소를 조회하면 됩니다.

예제:

queue[-1]

# "banana"

이런 연산을 peek(살짝 들여다보기)라고 부릅니다.

스레드에 안전한 Ruby 동시성 큐

Ruby는 스레드에 안전(thread-safe)하고 블로킹 방식으로 동작하는 Queue 클래스를 기본으로 제공합니다. 멀티스레드 프로그램에서 작업을 조율할 때 이 클래스를 활용할 수 있습니다.

예제:

que = Queue.new

que << 1
que << 2
que << 3

pop으로 큐에서 항목을 꺼낼 수 있습니다:

que.pop
# 1

que.pop
# 2

여기서 중요한 특징이 하나 있습니다. 큐가 비어 있는 상태에서 pop을 호출하면 현재 스레드가 잠들면서 새 항목이 추가될 때까지 대기합니다. 이것이 바로 "블로킹(blocking)"의 의미입니다.

블로킹 없이 즉시 결과를 받고 싶다면 poptrue를 전달하세요:

que.pop(true)

이 경우 큐가 비어 있으면 ThreadError: queue empty 예외가 발생합니다.

SizedQueue 사용 방법

SizedQueue는 일반 큐와 동일하지만 크기 제한이 있다는 점이 다릅니다.

예제:

que = SizedQueue.new(5)

큐가 가득 찬 상태에서 push(<<와 동일)를 호출하면, 현재 스레드가 일시 중단되고 큐에서 항목이 빠져나갈 때까지 대기합니다.

예제:

que.push(:bacon)

대기하는 대신 예외를 발생시키고 싶다면 두 번째 인자로 true를 전달하세요:

que.push(:bacon, true)

이 경우 ThreadError: queue full 예외가 발생합니다.

영상 튜토리얼

마무리

지금까지 Ruby에서 큐를 사용하는 방법을 알아봤습니다!

작업을 FIFO(선입선출, First-In-First-Out) 순서로 처리해야 한다면 큐가 정답입니다. 큐를 구현하는 방법은 두 가지로, 배열을 직접 활용하거나 내장된 Queue 클래스를 사용하는 것입니다.

읽어주셔서 감사합니다. 🙂