多线程的运用
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方法。