我正在详细研究Thread类。基本上,我一直在寻找一种优雅的机制,允许在创建线程时继承线程局部变量。例如,我想要创建的功能将确保
Thread.new do
self[:foo]="bar"
t1=Thread.new { puts self[:foo] }
end
=> “酒吧”
即。一个线程将继承它的调用线程的线程局部变量
所以我想到了重新定义Thread.new的想法,这样我就可以添加一个额外的步骤来将线程局部变量从当前线程复制到新线程中。像这样:
class Thread
def self.another_new(*args)
o=allocate
o.send(:initialize, *args)
Thread.current.keys.each{ |k| o[k]=Thread.current[k] }
o
end
end
但是当我尝试这个时,我收到以下错误:
:in `allocate': allocator undefined for Thread (TypeError)
我认为,由于Thread是Object的子类,它应该有一个有效的#allocate方法。情况不是这样吗?
有没有人对此有深入的了解,以及如何实现我正在寻找的功能。
提前致谢
史蒂夫答案 0 :(得分:1)
Thread.new do
Thread.current[:foo]="bar"
t1=Thread.new(Thread.current) do |parent|
puts parent[:foo] ? parent[:foo] : 'nothing'
end.join
end.join
#=> bar
<强>更新:强>
在irb中尝试:
class Thread
def self.another_new(*args)
parent = Thread.current
a = Thread.new(parent) do |parent|
parent.keys.each{ |k| Thread.current[k] = parent[k] }
yield
end
a
end
end
A = Thread.new do
Thread.current[:local_a]="A"
B1 =Thread.another_new do
C1 = Thread.another_new{p Thread.current[:local_a] }.join
end
B2 =Thread.another_new do
C2 = Thread.another_new{p Thread.current[:local_a] }.join
end
[B1, B2].each{|b| b.join }
end.join
"A"
"A"
答案 1 :(得分:0)
以下是基于@ CodeGroover建议的修订答案,其中包含一个简单的单元测试工具
class Thread
def self.inherit(*args, &block)
parent = Thread.current
t = Thread.new(parent, *args) do |parent|
parent.keys.each{ |k| Thread.current[k] = parent[k] }
yield *args
end
t
end
end
require 'test/unit'
require 'ext/thread'
class ThreadTest < Test::Unit::TestCase
def test_inherit
Thread.current[:foo]=1
m=Mutex.new
#check basic inheritence
t1= Thread.inherit do
assert_equal(1, Thread.current[:foo])
end
#check inheritence with parameters - in this case a mutex
t2= Thread.inherit(m) do |m|
assert_not_nil(m)
m.synchronize{ Thread.current[:bar]=2 }
assert_equal(1, Thread.current[:foo])
assert_equal(2, Thread.current[:bar])
sleep 0.1
end
#ensure t2 runs its mutexs-synchronized block first
sleep 0.05
#check that the inheritence works downwards only - not back up in reverse
m.synchronize do
assert_nil(Thread.current[:bar])
end
[t1,t2].each{|x| x.join }
end
end
答案 2 :(得分:0)
我最近在寻找同样的东西,并且能够想出以下答案。请注意,我知道以下是一种黑客行为,不推荐使用,但为了回答有关如何更改 Thread.new
功能的具体问题,我已执行以下操作:
class Thread
class << self
alias :original_new :new
def new(*args, **options, &block)
original_thread = Thread.current
instance = original_new(*args, **options, &block)
original_thread.keys.each do |key|
instance[key] = original_thread[key]
end
instance
end
end
end