Ruby中如何向可yield的Thread传递代码块?
如何给可yield的Ruby线程传递代码块?
嘿,这个场景我之前也碰到过!send()方法确实没法直接传代码块,因为它是用来调用已定义的方法名的,但咱们有更合适的办法来实现你要的功能——让休眠的线程在事件触发时执行动态代码块。下面给你几个实用的方案:
方案1:用队列(Queue)传递代码块
这是最直观且线程安全的方式,思路是让线程不再单纯休眠,而是监听一个队列,当触发事件时把代码块扔进队列,线程取出后执行:
require 'thread' # 创建线程安全的队列 task_queue = Queue.new # 初始化等待的线程 @@thread1 = Thread.new do loop do # 阻塞等待队列中的任务,拿到后执行 task = task_queue.pop task.call end end # 模拟用户点击事件:往队列里塞代码块 def trigger_event task_queue << -> { puts "执行动态代码块:处理用户点击" # 这里可以写任意你想要执行的逻辑 } end # 测试调用 trigger_event @@thread1.join
这个方案的好处是天然线程安全,队列会自动处理同步问题,而且可以连续传递多个代码块,线程会依次执行。
方案2:用条件变量(ConditionVariable)配合共享变量
如果需要更精细的控制(比如线程执行完代码块后回到等待状态),可以用条件变量来唤醒线程,同时用共享变量存储要执行的代码块:
require 'thread' mutex = Mutex.new cond = ConditionVariable.new current_block = nil @@thread1 = Thread.new do loop do mutex.synchronize do # 等待唤醒信号 cond.wait(mutex) # 执行代码块(如果有的话) current_block.call if current_block # 重置代码块,准备下一次等待 current_block = nil end end end # 触发事件时设置代码块并唤醒线程 def trigger_event(&block) mutex.synchronize do current_block = block cond.signal end end # 测试调用 trigger_event do puts "执行动态代码块:处理用户点击" end @@thread1.join
这种方式适合需要线程在执行完任务后立刻回到等待状态的场景,通过互斥锁保证共享变量的线程安全。
为什么send()不适合?
Thread#send()的作用是调用线程对象的方法(比如wakeup、join这些),它需要传入已定义的方法名,而你要传递的是动态的代码块,这和send()的设计初衷不符,所以没法直接用它来实现你的需求。
总结一下,推荐优先用队列的方案,逻辑简单且不容易出错,完全能满足你“事件触发时让线程执行不同代码块”的需求~
内容的提问来源于stack exchange,提问作者Tennesseej
相关产品推荐
相关产品推荐

