创建一个包含一些线程,执行任务并最终调用回调方法的类是我目前的目标,在这条路上没什么特别的。
我的实验类会对给定IP的特定端口进行一些连接检查,以便为我提供状态信息。
所以我的尝试:
check = ConnectionChecker.new do | threads |
# i am done callback
end
check.check_connectivity(ip0, port0, timeout0, identifier0)
check.check_connectivity(ip1, port1, timeout1, identifier1)
check.check_connectivity(ip2, port2, timeout2, identifier2)
sleep while not check.is_done
也许不是最好的方法,但总的来说它适合我的情况。
所以发生了什么:
在我的课程中,我会存储一个回调,执行操作并执行内部操作:
Thread.new
- >成功/失败 - >完成时标记为已完成 - >呼叫回叫:
class ConnectionChecker
attr_reader :is_done
def initialize(&callback)
@callback = callback
@thread_count = 0
@threads = []
@is_done = false
end
def check_connectivity(host, port, timeout, ident)
@thread_count += 1
@threads << Thread.new do
status = false
pid = Process.spawn("nc -z #{host} #{port} >/dev/null")
begin
Timeout.timeout(timeout) do
Process.wait(pid)
status = true
end
rescue Process::TimeoutError => e
Process.kill('TERM', pid)
end
mark_as_done
#returnvalue for the callback.
[status, ident]
end
end
# one less to go..
def mark_as_done
@thread_count -= 1
if @thread_count.zero?
@is_done = true
@callback.call(@threads)
end
end
end
这段代码 - 是的,我知道没有启动方法所以我必须相信我会立刻称之为 - 工作正常。
但是当我换掉这两行时:
@is_done = true
@callback.call(@threads)
到
@callback.call(@threads)
@is_done = true
然后是最后一行,
sleep while not check.is_done
成为无限循环。调试显示我正确调用了回调,当我检查is_done
的值时,它总是false
。由于我没有把它关闭,我想知道为什么会发生这种情况。
回调本身也可以为空,is_done
仍为false
(因此没有错误捕获的异常)。
在这种情况下,我注意到最后一个线程处于运行状态。由于我没有要求线程的价值,我只是不在这里。
有关此问题的任何文档/信息?此外,它的名称也没问题。
答案 0 :(得分:1)
尝试使用Mutex确保线程安全:)