類別 Thread::Queue

Thread::Queue 類別實作多重產生者、多重消費者佇列。特別適用於執行緒程式設計,當資訊必須在多個執行緒之間安全地交換時。Thread::Queue 類別實作所有必要的鎖定語意。

此類別實作 FIFO (先進先出) 型式的佇列。在 FIFO 佇列中,最先加入的任務會最先被擷取。

範例

queue = Thread::Queue.new

producer = Thread.new do
  5.times do |i|
    sleep rand(i) # simulate expense
    queue << i
    puts "#{i} produced"
  end
end

consumer = Thread.new do
  5.times do |i|
    value = queue.pop
    sleep rand(i/2) # simulate expense
    puts "consumed #{value}"
  end
end

consumer.join

公開類別方法

Thread::Queue.new → empty_queue 按一下以切換來源
Thread::Queue.new(enumerable) → queue

建立新的佇列實例,選擇性地使用 enumerable 的內容作為其初始狀態。

範例

q = Thread::Queue.new
#=> #<Thread::Queue:0x00007ff7501110d0>
q.empty?
#=> true

q = Thread::Queue.new([1, 2, 3])
#=> #<Thread::Queue:0x00007ff7500ec500>
q.empty?
#=> false
q.pop
#=> 1
static VALUE
rb_queue_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE initial;
    struct rb_queue *q = queue_ptr(self);
    if ((argc = rb_scan_args(argc, argv, "01", &initial)) == 1) {
        initial = rb_to_array(initial);
    }
    RB_OBJ_WRITE(self, queue_list(q), ary_buf_new());
    ccan_list_head_init(queue_waitq(q));
    if (argc == 1) {
        rb_ary_concat(q->que, initial);
    }
    return self;
}

公開實例方法

<<(object)

將給定的 object 推入佇列。

別名:push
clear() 按一下以切換來源

從佇列中移除所有物件。

static VALUE
rb_queue_clear(VALUE self)
{
    struct rb_queue *q = queue_ptr(self);

    rb_ary_clear(check_array(self, q->que));
    return self;
}
close 按一下以切換來源

關閉佇列。已關閉的佇列無法重新開啟。

在呼叫 close 完成後,下列敘述為真

  • closed? 會傳回 true

  • close 會被忽略。

  • 呼叫 enq/push/<< 會引發 ClosedQueueError

  • empty? 為 false 時,呼叫 deq/pop/shift 會像往常一樣從佇列傳回物件。

  • empty? 為 true 時,deq(false) 不會暫停執行緒,且會傳回 nil。deq(true) 會引發 ThreadError

ClosedQueueErrorStopIteration 繼承,因此您可以中斷迴圈區塊。

範例

q = Thread::Queue.new
Thread.new{
  while e = q.deq # wait for nil to break loop
    # ...
  end
}
q.close
static VALUE
rb_queue_close(VALUE self)
{
    struct rb_queue *q = queue_ptr(self);

    if (!queue_closed_p(self)) {
        FL_SET(self, QUEUE_CLOSED);

        wakeup_all(queue_waitq(q));
    }

    return self;
}
closed? 按一下以切換來源

如果佇列已關閉,則傳回 true

static VALUE
rb_queue_closed_p(VALUE self)
{
    return RBOOL(queue_closed_p(self));
}
deq
別名:pop
empty? 按一下以切換來源

如果佇列為空,則傳回 true

static VALUE
rb_queue_empty_p(VALUE self)
{
    return RBOOL(queue_length(self, queue_ptr(self)) == 0);
}
enq(object)

將給定的 object 推入佇列。

別名:push
freeze 按一下以切換來源

佇列無法凍結,因此此方法會引發例外狀況

Thread::Queue.new.freeze # Raises TypeError (cannot freeze #<Thread::Queue:0x...>)
static VALUE
rb_queue_freeze(VALUE self)
{
    rb_raise(rb_eTypeError, "cannot freeze " "%+"PRIsVALUE, self);
    UNREACHABLE_RETURN(self);
}
length 按一下以切換來源
大小

傳回佇列的長度。

static VALUE
rb_queue_length(VALUE self)
{
    return LONG2NUM(queue_length(self, queue_ptr(self)));
}
別名:size
num_waiting() 按一下以切換來源

傳回在佇列中等待的執行緒數目。

static VALUE
rb_queue_num_waiting(VALUE self)
{
    struct rb_queue *q = queue_ptr(self);

    return INT2NUM(q->num_waiting);
}
pop(non_block=false, timeout: nil) 按一下以切換來源

從佇列中擷取資料。

如果佇列為空,則呼叫執行緒會暫停,直到資料推送到佇列中。如果 non_block 為 true,則執行緒不會暫停,並且會引發 ThreadError

如果已過 timeout 秒,但沒有資料可用,則會傳回 nil。如果 timeout0,則會立即傳回。

# File thread_sync.rb, line 14
def pop(non_block = false, timeout: nil)
  if non_block && timeout
    raise ArgumentError, "can't set a timeout if non_block is enabled"
  end
  Primitive.rb_queue_pop(non_block, timeout)
end
別名:deq, shift
push(object) 按一下以切換來源

將給定的 object 推入佇列。

static VALUE
rb_queue_push(VALUE self, VALUE obj)
{
    return queue_do_push(self, queue_ptr(self), obj);
}
別名:enq, <<
shift
別名:pop
length
大小

傳回佇列的長度。

別名:length