在ruby中,是否可能导致线程从另一个并发运行的线程暂停。
以下是我到目前为止编写的代码。我希望用户能够输入'pause thread'和sample500线程来暂停。
#!/usr/bin/env ruby
# Creates a new thread executes the block every intervalSec for durationSec.
def DoEvery(thread, intervalSec, durationSec)
thread = Thread.new do
start = Time.now
timeTakenToComplete = 0
loopCounter = 0
while(timeTakenToComplete < durationSec && loopCounter += 1)
yield
finish = Time.now
timeTakenToComplete = finish - start
sleep(intervalSec*loopCounter - timeTakenToComplete)
end
end
end
# User input loop.
exit = nil
while(!exit)
userInput = gets
case userInput
when "start thread\n"
sample500 = Thread
beginTime = Time.now
DoEvery(sample500, 0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")}}
when "pause thread\n"
sample500.stop
when "resume thread"
sample500.run
when "exit\n"
exit = TRUE
end
end
答案 0 :(得分:3)
将Thread对象作为参数传递给DoEvery
函数是没有意义的,因为你立即用Thread.new覆盖它,看看这个修改过的版本:
def DoEvery(intervalSec, durationSec)
thread = Thread.new do
start = Time.now
Thread.current["stop"] = false
timeTakenToComplete = 0
loopCounter = 0
while(timeTakenToComplete < durationSec && loopCounter += 1)
if Thread.current["stop"]
Thread.current["stop"] = false
puts "paused"
Thread.stop
end
yield
finish = Time.now
timeTakenToComplete = finish - start
sleep(intervalSec*loopCounter - timeTakenToComplete)
end
end
thread
end
# User input loop.
exit = nil
while(!exit)
userInput = gets
case userInput
when "start thread\n"
sample500 = DoEvery(0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")} }
when "pause thread\n"
sample500["stop"] = true
when "resume thread\n"
sample500.run
when "exit\n"
exit = TRUE
end
end
这里DoEvery
返回新的线程对象。另请注意,Thread.stop在运行线程内部调用,不能直接从另一个线程中停止,因为它不安全。
答案 1 :(得分:2)
您可以更好地完成使用Ruby Fiber对象的尝试,并可能在运行的系统上实现更高的效率。
光纤是实现轻量级合作的基本原则 Ruby中的并发性。基本上它们是创建代码的一种手段 可以暂停和恢复的块,就像线程一样。主要的 区别在于它们永远不会被抢占和调度 必须由程序员而不是VM完成。
请记住当前MRI Ruby的实现不提供任何并发运行线程,并且您能够完成的最好的是green threaded程序,以下是一个很好的示例:
require "fiber"
f1 = Fiber.new { |f2| f2.resume Fiber.current; while true; puts "A"; f2.transfer; end }
f2 = Fiber.new { |f1| f1.transfer; while true; puts "B"; f1.transfer; end }
f1.resume f2 # =>
# A
# B
# A
# B
# .
# .
# .