第一个:
如何创建一个不立即启动的线程。如果我在没有块的情况下使用initialize
,则会引发异常。
我怎样才能将Thread子类化,以便我可以添加一些自定义属性,但保留与基本Thread类相同的功能?我也不想使用initialize(&block)
方法。
为了更好地说明这一点:
对于第一个问题:
x = Thread.new
x.run = {
# this should happen inside the thread
}
x.start # i want to manually start the thread
第二个:
x = MyThread.new
x.my_attribute = some_value
x.run = {
# this should happen when the thread runs
}
x.start
我正在寻找类似的东西。希望你能帮忙。
答案 0 :(得分:11)
问题1
检查MRI 1.8.7来源显示没有明显的方法来启动处于“停止”状态的线程。
您可以做的是让线程阻塞在锁定的互斥锁上,然后在需要线程时解锁互斥锁。
#!/usr/bin/ruby1.8
go = Mutex.new
go.lock
t = Thread.new do
puts "Thread waiting to go"
go.lock
puts "Thread going"
end
puts "Telling the thread to go"
go.unlock
puts "Waiting for the thread to complete"
t.join
# => Thread waiting to go
# => Telling the thread to go
# => Thread going
# => Waiting for the thread to complete
问题2(排序)
您知道可以将参数传递给您的帖子吗?传递给Thread.new的任何东西都作为块参数传递:
#!/usr/bin/ruby1.8
t = Thread.new(1, 2, 3) do |a, b, c|
puts "Thread arguments: #{[a, b, c].inspect}"
# => Thread arguments: [1, 2, 3]
end
还有“线程局部变量”,每线程键/值存储。使用Thread#[]=
设置值,使用Thread#[]
将其恢复。您可以使用字符串或符号作为键。
#!/usr/bin/ruby1.8
go = Mutex.new
go.lock
t = Thread.new(1, 2, 3) do |a, b, c|
go.lock
p Thread.current[:foo] # => "Foo!"
end
t[:foo] = "Foo!"
go.unlock
t.join
问题2,真的
你可以做你想做的事。这是一项很多工作,特别是当处理线程的常用方法非常简单时。你必须权衡利弊:
#!/usr/bin/ruby1.8
require 'forwardable'
class MyThread
extend Forwardable
def_delegator :@thread, :join
def_delegator :@thread, :[]=
def_delegator :@thread, :[]
def initialize
@go = Mutex.new
@go.lock
@thread = Thread.new do
@go.lock
@stufftodo.call
end
end
def run(&block)
@stufftodo = block
@go.unlock
@thread.join
end
end
t = MyThread.new
t[:foo] = "Foo!"
t.run do
puts Thread.current[:foo]
end
t.join
# => "Foo!"
答案 1 :(得分:3)
stuff_to_do = lambda do
# this happens in the thread
end
x = Thread.new( &stuff_to_do )
答案 2 :(得分:2)
忽略example from Ruby-Doc 1.8.7,因为它包含竞争条件。请参阅Ruby 2 example,或类似以下内容:
我在Ruby 2.0和Ruby 1.8.7中对此进行了测试,我发现在1.8.7中调用#wakeup
是不够的'我必须调用#run
。以下似乎适用于:
t = Thread.new { Thread.stop; puts "HELLO" }
until t.stop?; end # ensure thread has actually stopped before we tell it to resume
t.run