ruby – 在线程内部引发同步错误
使用以下脚本
threads = [ Thread.new { Thread.current.abort_on_exception = true; raise 'err' },Thread.new { Thread.current.abort_on_exception = true; raise 'err' },] begin threads.each(&:join) rescue RuntimeError puts "Got Error" end 有一半时间我得到预期的“Got Error”,退出0,另一半得到test.rb:3:在< main>‘中的块:err(RuntimeError). 不应该救援能够处理这个吗?如果没有什么可能是两个线程同时引发错误的替代解决方案? 我已经考虑过不使用abort_on_exception = true但是问题是如果第一个线程有,比如说在加注之前睡眠(10),第二个线程会立即出错,直到10秒钟才会被捕获(由于线程数组的顺序). Ruby MRI版本: 任何想法将不胜感激.谢谢! 更新 jruby-9.1.6.0似乎没有这个问题.可能是因为它固有的线程安全性.它始终打印Got Error,没有任何异常.不幸的是,JRuby不适合我们. 解决方法
这里有几个难题.
首先,程序只等待主线程完成: Thread.new { Thread.current.abort_on_exception = true; raise 'Oh,no!' } puts 'Ready or not,here I come' 以上可能会或可能不会引起错误. 其次,如果你加入一个线程,那个线程引发的异常将由#join方法的连接线程重新引发: gollum = Thread.new { raise 'My precious!!!' } begin gollum.join rescue => e # Prints 'My precious!!!' puts e.message end 此时,执行将返回到已加入的线程.它不再加入导致错误的线程或任何其他线程.它没有加入其他线程的原因是因为你当时只能加入一个线程. threads.each(& join)实际上将你连接到第一个,当它结束时 – 到第二个,依此类推: frodo = Thread.new { raise 'Oh,no,Frodo!' } sam = Thread.new { raise 'Oh,Sam!' } begin [frodo,sam].each(&:join) rescue => e puts e.message end puts 'This is the end,my only friend,the end.' 以上打印
现在让我们把它放在一起: frodo = Thread.new { Thread.current.abort_on_exception = true; raise 'Oh,Frodo!' } sam = Thread.new { Thread.current.abort_on_exception = true; raise 'Oh,the end.' 这里可能发生很多事情.重要的是,如果我们设法加入(在此之前我们没有得到错误),救援将从主线程中捕获异常,从任何线程设法先提升它然后在救援后继续.之后,主线程(以及程序)可能会或可能不会在另一个线程引发其异常之前完成. 让我们检查一些可能的输出
在我们加入之前,佛罗多提出了他的例外.
我们加入后,Sam是第一个提出错误的人.在主线程中打印出错误消息后,我们也打印了结束.然后主线程完成,在Frodo可以提出他的错误之前.
我们成功加入.佛罗多是第一个筹集,我们获救和印刷. Sam在我们打印结束之前加注了.
(很少)我们设法得救了. Sam首先提出错误,然后从主线程中打印出来.我们打印了结束.在打印之后,但在主线程终止之前,Frodo也成功地抓住了他的错误. 至于一个可能的解决方案,你需要尽可能多的救援,因为有可能引起的线程.请注意,我还将线程创建放在受保护的块中,以确保我们在连接之前捕获潜在的错误: def execute_safely_concurrently(number_of_threads,&work) return if number_of_threads.zero? begin Thread.new(&work).join rescue => e puts e end execute_safely_concurrently(number_of_threads.pred,&work) end execute_safely_concurrently(2) do Thread.current.abort_on_exception = true raise 'Handle me,bitte!' end (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |