`
edwardpro
  • 浏览: 300580 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Thread In Ruby

阅读更多

今日终于把原来留下来的ios notify给整了,由于用户数据的增加这个库显然力不从心,过程就不说了。

这个东西原来是rails 3写的,APN发送也有现成的库用gem装下就能用了,关键在于原来的发送任务,由于rails 3中提供了一个基于redis的分布式任务系统,但这个东西自从我升级了redis后就再跑不起来,调试了几下也没有太多成果,时间来不及了,于是用了ruby下的Thread包。

 

今天想把自己使用Thread在ruby下进行多线程编程的内容分享一下:

 

1 base的使用非常简单:

 

 

Thread.new(args...){|args...|}

 

 

当然还有fork和start方法本质上差别不大,我都是用的new,start实际上是new的别名(也可能是反过来,反正记住这两个没差别就是了。

 

2 多线程的同步处理:

 

由于ruby实际上是一个脚本语言,它并没有像java一样复杂的内存管理区块(至少看起来没有,有几个点证明的,我后面会说)但是ruby提供了非常简单一些同步处理的方法。

 

首先如果你要同步等待一个Thread,可以这么写:

thread = Thread.new{}
thread.join

 join 以后,就意味着它的父thread就必须等待它执行完毕才能继续后面的代码,于是比如在循环中你可以通过这个来进行同步等待,这个比在java中还是要方便不少,当然这玩意是脚本语言不方便就不对了。

for n in [1...10] 
thread=Thread.new{}
thread.join
end

 接下来线程的顺序,这个方法是看来的:

thread1 = Thread.new{self.stop; xxxxx}
thread2 = Thread.new{self.stop; xxxxx}
thread3 = Thread.new{self.stop; xxxxx}
thread1.join
thread1.start
thread2.join
thread2.start
thread3.join
thread3.start

 上述代码还可以用来做类似java里的执行器功能即可。

 

3 关于thread特别注意的地方:

 

线程里的上下文是干净和独立的,thread里虽然是一个内部类的实现,但是它本身不能共享上面的数据,所以当你要传参的时候必须使用参数方法

 

 

Thread.new(a){xxxxx}

 这个我一开始很不习惯,突然发现父类的东西都nil了。。。后来才发现这个道理,于是我的第一个猜想就是ruby的内存管理是一种stack而且为了避免线程污染的问题,它应该没有真正意义的堆,所以你可以认为它是一种非常纯正的oo语言,不像java还是可以写出很op的代码的,在ruby里似乎的确这样会让让你崩溃,特别是线程里。

 

关闭资源需要在线程中控制:

 

比如你在线程里传入一个文件句柄,那么我们必须在线程里自己关闭,而且是子底向上的,不然就会出现文件句柄在线程执行时被关闭的问题,如:

file = File.new("xxxx","w")
begin
for n in [1...10]
Thread.new(file){file.write("test\n#{n}")}
end
ensure
file.close #这个是错误的
end
 

 

这种写法100%会导致你的日志里打出来,文件已经被关闭的错误提示。如果你想这么做那么线程必须被join,这样就没有意义了,理论上这种类似功能可以在外面再套一个thread这样就可以保证上述功能成功,因为我在一个子线程中等待就ok了。虽然这样看起来很麻烦,但是仔细想想这样的设计就是不让你产生所谓的线程不安全的问题,这个比java还是方便和“低技术”不少。

 

ok利用Thread实际上基本上就能实现rails3中的基于redis的任务系统了,这样的过程还是蛮有意思的虽然过程也很痛苦,特别是当我想看ruby时发现电脑里就2本电子书,而纸质书全部找不到了,这个真的擦啊。。。

 

好了,晚安,碎觉!

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics