说我有一个班级Talker
。我正在使用一个队列让Talker说话,但我偶尔想让说话者静音,但是当我取消对说话者的静音时,我希望说话者能够从他离开的地方继续前进。如何阻止线程从队列中获取消息并等待我取消静音以恢复通话?
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 :(得分:0)
虽然ruby绝对不是处理异步操作的最佳选择,但仍然可以使用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
代码未经测试,但我相信它应该可行。
答案 1 :(得分: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
和读取它的线程之间存在争用时,静音和线程实际停止之间也可能会略有延迟。
这可能不是一个好习惯,但如果我是你,我甚至会放弃互斥锁。对于布尔标志,如果同时发生多次写入,则没有区别。