淘先锋技术网

首页 1 2 3 4 5 6 7

多线程的运用

def func2
   j=0
   while j<=2
      puts "func2 at: #{Time.now}"
      sleep(1)
      j=j+1
   end
end

1.new可以用于创建线程,Thread也可以使用相同的语法Start或Thread。fork用于创建线程。
2.创建线程后,无需启动,线程将自动执行。
3.Thread类定义了一些处理线程的方法。线程执行thread.new中的代码块。
4.线程代码块中的最后一条语句是线程的值,它可以通过线程的方法调用。如果线程完成执行,则返回线程值;否则,在线程完成执行之前,不会返回该值。
5.线程。当前方法返回表示当前线程的对象。线main方法返回主线程。
6.通过Thread Join方法执行线程。此方法将暂停主线程,直到当前线程完成执行。

puts "Started At #{Time.now}"
t1=Thread.new{func1()}
t2=Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"

系统上运行的每个程序都是一个进程。每个进程包含一个或多个线程。
线程是程序中的单序列控制流。在一个程序中同时运行多个线程以完成不同的工作称为多线程。
在Ruby中,我们可以通过Thread类创建多个线程。Ruby线程是轻量级的,可以以高效的方式实现并行代码。

def func1
   i=0
   while i<=2
      puts "func1 at: #{Time.now}"
      sleep(2)
      i=i+1
   end
end

线程发生异常

当线程发生异常且未被救援捕获时,通常会在没有警告的情况下终止线程。但是,如果其他线程由于thread#join关系一直在等待该线程,则等待线程也将抛出相同的异常。

begin
  t = Thread.new do
    Thread.pass 
    raise "unhandled exception"
  end
  t.join
rescue
  p $!  # => "unhandled exception"
end

主线程确实在等join。
使用以下三种方法,可以在线程因异常而终止时中断解释器。

  • 在启动脚本时指定-d选项,并在调试模式下运行它。
  • 使用Thread.art_on_exception设置标志。
  • 使用线程#abort_on_Exception设置指定线程的标志。

当使用上述三种方法之一时,整个解释器将被中断。

同步控制

在Ruby中,提供了三种同步方法:
1.通过Mutex类实现线程同步
2.用于监控数据切换的Queue类实现线程同步
3.使用ConditionVariable实现同步控制
通过Mutex类进行线程同步
Mutex类实现线程同步控制。如果同时需要多个线程时钟使用程序变量,则可以使用lock来锁定该变量。代码如下:

@num=200
@mutex=Mutex.new
 
def buyTicket(num)
     @mutex.lock
          if @num>=num
               @num=@num-num
               puts "you have successfully bought #{num} tickets"
          else
               puts "sorry,no enough tickets"
          end
     @mutex.unlock
end
 
ticket1=Thread.new 10 do
     10.times do |value|
     ticketNum=15
     buyTicket(ticketNum)
     sleep 0.01
     end
end
 
ticket2=Thread.new 10 do
     10.times do |value|
     ticketNum=20
     buyTicket(ticketNum)
     sleep 0.01
     end
end

除了使用锁锁定变量外,还可以使用try_lock锁定变量。您也可以使用Mutex.synchronize来同步对变量的访问。
用于监视数据切换的Queue类实现线程同步
Queue类表示支持线程并可以同步访问队列末尾的队列。不同的线程可以使用一对统一的类,但不要担心队列中的数据是否可以同步。此外,使用SizedQueue类可以限制队列的长度
SizedQueue类可以帮助我们非常方便地开发线程同步应用程序。只要我们加入这个队列,就不需要关心线程同步。

sleep 1
ticket1.join
ticket2.join

线程可以有自己的私有变量

线程可以有自己的私有变量,在创建线程时将其写入线程。它可以在线程范围内使用,但不能在线程外共享。
但有时,如果一个线程的局部变量需要由另一个线程或主线程访问呢?Ruby提供了按名称创建线程变量的能力,类似地将线程视为哈希表。通过[]=写入数据,通过[]读取数据。

count = 0
arr = []
 
10.times do |i|
   arr[i] = Thread.new {
      sleep(rand(0)/10.0)
      Thread.current["mycount"] = count
      count += 1
   }
end

线程的优先级是影响线程调度的主要因素。其他因素包括CPU的执行时间、线程分组调度等。
您可以使用线程。priority方法获取线程优先级和线程。priority=调整线程优先级的方法。
默认情况下,线程的优先级为0。优先级越高,执行速度越快。
一个线程可以访问其自身范围内的所有数据,但如果它需要访问线程中其他线程的数据。
Thread类为线程提供了一种访问彼此数据的方法。您可以简单地将线程用作哈希表。您可以使用[]=在任何线程中写入数据,使用[]读取数据。

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      count1 += 1
      count2 += 1
   end
end
spy = Thread.new do
   loop do
      difference += (count1 - count2).abs
   end
end

死锁处理

当两个或多个计算单元正在等待对方停止运行以获取系统资源,但都没有提前退出时,这种情况称为死锁。
例如,进程p1占用显示器并且必须使用打印机,而打印机被进程p2占用并且p2必须使用显示器,这形成了死锁。
当使用Mutex对象时,我们需要注意线程死锁。

cv = ConditionVariable.new
a = Thread.new {
   mutex.synchronize {
      puts "A: I have critical section, but will wait for cv"
      cv.wait(mutex)
      puts "A: I have critical section again! I rule!"
   }
}
 
puts "(Later, back at the ranch...)"
 
b = Thread.new {
   mutex.synchronize {
      puts "B: Now I am critical, but am done with cv"
      cv.signal
      puts "B: I am still critical, finishing up"
   }
}

通常,正常的程序执行路径是单行执行。按编码顺序执行程序中的所有语句。然而,在多线程程序中,可以在多个路径中执行多个程序。多线程使用更少的内存空间并共享相同的地址空间。多线程用于同时执行多个任务。
创建线程后,无需启动线程。它在获得正确的CPU资源后自动运行。块中的最后一个表达式是线程的值。如果线程完全运行,value方法将返回线程值。否则,value方法将在线程完成时阻塞并返回。线程类在运行查询和操作线程时定义了一些方法。
通过调用线程的Thread.java方法。