确保线程执行

让我们回到我们之前的程序中遇到的问题。回想一下,我们创建了两个线程,但程序在其中任何一个线程运行之前就已完成。我们通过使用 sleep 方法插入固定长度的延迟来解决这个问题。但是有意在你的程序中引入没有额外作用的延迟并不是你想要做的通用规则。幸运的是,Ruby 有一种更加优雅的方式来确保线程有时间执行。join 方法强制调用线程(例如主线程)挂起自己的执行(因此它不只是终止程序),直到调用 join 的线程完成:

join.rb
  1. words = ["hello", "world", "goodbye", "mars" ]
  2. numbers = [1,2,3,4,5,6,7,8,9,10]
  3. Thread.new{
  4. words.each{ |word| puts( word ) }
  5. }.join
  6. Thread.new{
  7. numbers.each{ |number| puts( number ) }
  8. }.join

乍一看,这似乎是进步了,因为两个线程都需要执行它们所需的时间,我们不必引入任何不必要的延迟。但是,当你查看输出时,你将看到线程按顺序运行 - 第二个线程在第一个线程完成后开始运行。但我们真正想做的是让两个线程同时运行,Ruby 从一个线程切换到另一个线程,为每个线程提供一小部分可用的处理时间。

下一个程序 threads3.rb 显示了实现这一目标的一种方式。它像之前一样创建两个线程;但是,这次它将每个线程分配给一个变量:wordsThreadnumbersThread

threads3.rb
  1. wordsThread = Thread.new{
  2. words.each{ |word| puts( word ) }
  3. }
  4. numbersThread = Thread.new{
  5. numbers.each{ |number| puts( number ) }
  6. }

现在它将这些线程放入一个数组中并调用 each 方法将它们传递到一个块中,块变量 t 接收它们,它只是在每个线程上调用 join 方法:

  1. [wordsThread, numbersThread].each{ |t| t.join }

正如你将从输出中看到的那样,两个线程现在“并行”(in parallel)运行,因此它们的输出混乱,但没有人为延迟,总执行时间可以忽略不计。