【发布时间】:2012-05-03 01:24:03
【问题描述】:
对于this answer,我写了如下代码:
def show_wait_spinner
dirty = false
spinner = Thread.new{
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
}
yield
spinner.kill
print "\b" if dirty
end
print "A"
show_wait_spinner{ sleep rand }
puts "B"
目标是确保最终输出为"AB"——如果线程尚未打印最终的"\b",则打印它。在 begin/rescue/ensure 存在的 Ruby 中,该代码对我来说似乎很乱。所以我尝试了show_wait_spinner的其他一些实现;他们都无法确保"AB" 始终是输出,而不是"A*B" 或"AB*"。
是否有一种更简洁、更符合 Ruby 风格的方式来实现此逻辑?
通过 Mutex 在循环结束时停止
def show_wait_spinner
stop = false
stopm = Mutex.new
spinner = Thread.new{
loop{
print "*"
sleep 0.1
print "\b"
stopm.synchronize{ break if stop }
}
}
yield
stopm.synchronize{ stop = true }
STDOUT.flush
end
...但是我的逻辑一定是错误的,因为这总是导致“A*B”。
通过线程局部变量在循环结束时停止
第二次尝试导致有时打印“A*B”,有时打印“AB”:
def show_wait_spinner
stop = false
spinner = Thread.new{
Thread.current[:stop] = false
loop{
print "*"
sleep 0.1
print "\b"
stopm.synchronize{ break if Thread.current[:stop] }
}
}
yield
spinner[:stop] = true
STDOUT.flush
end
杀死并确保线程
def show_wait_spinner
spinner = Thread.new{
dirty = false
begin
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
ensure
print "\b" if dirty
end
}
yield
spinner.kill
STDOUT.flush
end
提升和拯救线程
def show_wait_spinner
spinner = Thread.new{
dirty = false
begin
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
rescue
puts "YAY"
print "\b" if dirty
end
}
yield
spinner.raise
STDOUT.flush
end
【问题讨论】:
标签: ruby multithreading console