require '******' #====drb client 生成的gem
p Thread.list
a = ARGV.first
ts = []
a.to_i.times do |i|
ts << Thread.new(i) do
Thread.stop
sleep(i+1)
p i+1
end
end
ts.each{|t| t.run}
ts.each &:join
=begin
ruby a.rb 10
[#<Thread:0x000000020ee640 run>, #<Thread:0x00000005035188 sleep>]
1
2
4
5
6
7
8
9
10
=end
该实例结果一直处于等待某一线程,how to deal with it
不明白,不明白,既然要等待子线程跑完,就不用先 stop 再 run 了
p Thread.list
a = ARGV.first
ts = []
a.to_i.times do |i|
ts << Thread.new(i) do
#Thread.stop
sleep(i+1)
p i+1
end
end
# 加上这个就会等很久很久才退出
# ts << Thread.new { sleep 10**100 }
#ts.each{|t| t.run}
ts.each(&:join)
# map 可以把所有进程的状态输出, happy!
# puts ts.map(&:join)
线程里面先 stop 再 run 是不可行的,因为你的线程可能还没来得及 stop 就已经先执行 run 的命令了。只是因为你线程第一次执行的命令是 Thead.stop,所以这个可能性比较小,但是多试几次还是会出现这种情况的。如果线程一直保持 stop,你再去 join 它就会出现 deadlock
[#<Thread:0x000000006c2668 run>]
1
3
4
5
6
7
8
9
10
test.rb:12:in `join': No live threads left. Deadlock? (fatal)
from test.rb:12:in `block in <main>'
from test.rb:12:in `map'
from test.rb:12:in `<main>'
PS: 其实我还是不懂你要啥效果=_=
以下都是执行 10 次的结果 ruby a_test.rb 10
#encoding: utf-8
require '*******' #====drb client 生成的gem
require 'benchmark'
real_time = Benchmark.realtime do
a = ARGV.first
ts = []
t = []
a.to_i.times do |i|
ts << Thread.new(i) do
ti = Benchmark.realtime do
sleep(1)
end
t << ti
end.join
end
p t
sum = t.inject{|s,e| s=s+e}
p sum/t.size
end
p real_time
运行结果为
[1.000672781, 1.000814113, 1.000668882, 1.000586453, 1.000551037, 1.000492891, 1.000694687, 1.000767984, 1.000800398, 1.000598385]
1.0006647611000001
10.01287766 #==>总共耗时10s
所以加了 stop 和 run 操作;but 修改之后如:
#encoding: utf-8
require '*******'
require 'benchmark'
real_time = Benchmark.realtime do
a = ARGV.first
ts = []
t = []
a.to_i.times do |i|
ts << Thread.new(i) do
Thread.stop
ti = Benchmark.realtime do
sleep(1)
end
t << ti
end
end
ts.each &:run
ts.each &:join #有时主线程会一直等待第一个 ts[0]线程的运行 ts[0]没有运行结果所以修改为ts[4..-1].each &:join
p t
sum = t.inject{|s,e| s=s+e}
p sum/t.size
end
p real_time
修改 ts[4..-1].each &:join 之后也会出现等待状态 但是执行成功的几率比较大。结果如下:
[1.001274903, 1.000687374, 1.000907523, 1.001395518, 1.000877703, 1.001985597, 1.002118701, 1.00204419, 1.002451825] ##基本上size为8或者9
1.001527037111111
1.021161041 ##总耗时比较短 所以用了stop操作
我只用于测试一些方法的具体时间(模拟高并发情况下);ts join 会出现等待主线程一直等待状态,请大神解惑
做个广告。。。。自己做的 gem,https://github.com/xuxiangyang/go_chanel 用来封装线程执行的细节。只需要关心每一步的并发量就好了
#13 楼 @shiningray 本质上没什么区别,因为我写的时候是因为我们的系统需要一个这种东西。我又没有找到,就自己写了一个。现在就在线上系统中用了。
区别应该是不用控制并发。 我对 golang 中的 channel 和 go 进行了封装,你不用考虑线程间的同步,各种乱七八糟的问题,只需要把你自己的业务拆分成几步,每一步定好他的并发量,然后上一步的返回值是下一步的输入值,就 ok 了。
并且我没有引入其他的新概念,比如 select 什么的。这样学习成本更低一些。 在我看来,如果是用 ruby,那么对于并发量的要求不会那么高,如果并发量很大,我觉得应该用 golang。