2017-10-19 56 views
0

假設我有一個類Talker。我使用一個隊列來讓發言者說話,但我偶爾想要讓發言者靜音,但是當我取消發言者的靜音時,我希望發言人在他離開的地方繼續發言。如何阻止線程從隊列中獲取消息,並等待我取消靜音以恢復發言者的身份?從Ruby中的處理隊列中暫停線程

class Talker 
    def initialize 
    @queue = Queue.new 
    @threads = Array.new(1) do 
     Thread.new do 
     until @queue.empty? 
      # what logic should go here to check if mute 
      # and stop taking messages? 
      next_msg = @queue.shift 

      puts next_msg 
     end 
     end 
    end 
    end 

    def speak(msg) 
    @queue.push(msg) 
    end 

    # stop threads from taking messages from queue 
    def mute 
    # what goes here? 
    end 

    # allow threads to continuing taking messages from queue 
    def unmute 
    # what goes here? 
    end 
end 

回答

0

雖然紅寶石是絕對不適合處理異步操作的最佳選擇,人們仍然可以使用Thread::Mutex

@handler = Class.new do 
    @locks = {} 

    def mute(id, mutex) 
    @locks[id] ||= mutex.lock 
    end 

    def unmute(id) 
    @locks[id].unlock if @locks[id].is_a?(Thread::Mutex) 
    @locks.delete(id) 
    end 
end 


Thread.new do 
    MX = Thread::Mutex.new 
    until @queue.empty? 
    MX.synchronize do 
     next_msg = @queue.shift 
     puts next_msg 
    end 
    end 
end 

# stop threads from taking messages from queue 
def mute 
    @handler.mute(self, MX) 
end 

# allow threads to continuing taking messages from queue 
def unmute 
    @handler.unmute(self) 
end 

的代碼是未經測試,但我相信它應該工作。

0

而不是每個線程一個互斥體,你可以有一個互斥

class Talker 
    def initialize 
    @muted = false 
    @muted_mutex = Thread::Mutex.new 

    @queue = Queue.new 
    @threads = Array.new(1) do 
     Thread.new do 
     until @queue.empty? 
      next if @muted # skip this iteration 
      puts @queue.shift 
     end 
     end 
    end 
    end 

    def mute 
    @muted_mutex.synchronize { @muted = true } 
    end 

    def unmute 
    @muted_mutex.synchronize { @muted = false } 
    end 
end 

這一點,並有每線程互斥的是,這隻會阻止如果多個線程之間的區別保護的一個簡單標誌(嘗試同時靜音/取消靜音。但是,由於在設置@muted = false和讀取它的線程之間存在競爭,因此在靜音和線程實際停止之間可能會稍微延遲。

這可能不被認爲是好的做法,但如果我是你,我甚至會拋棄互斥體。對於布爾標誌,如果同時發生多個寫入,則不會產生任何影響。