多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

中國最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2

ruby教程

Ruby 多線程

閱讀 (2231)

Ruby 多線程

每個正在系統上運行的程序都是一個進程。每個進程包含一到多個線程。

線程是程序中一個單一的順序控制流程,在單個程序中同時運行多個線程完成不同的工作,稱為多線程。

Ruby 中我們可以通過 Thread 類來創建多線程,Ruby的線程是一個輕量級的,可以以高效的方式來實現并行的代碼。


創建 Ruby 線程

要啟動一個新的線程,只需要調用 Thread.new 即可:

# 線程 #1 代碼部分
Thread.new {
  # 線程 #2 執行代碼
}
# 線程 #1 執行代碼

實例

以下實例展示了如何在Ruby程序中使用多線程:

#!/usr/bin/ruby

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

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

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

嘗試一下 ?


以上代碼執行結果為:

Started At Wed May 14 08:21:54 -0700 2014
func1 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:55 -0700 2014
func1 at: Wed May 14 08:21:56 -0700 2014
func2 at: Wed May 14 08:21:56 -0700 2014
func1 at: Wed May 14 08:21:58 -0700 2014
End at Wed May 14 08:22:00 -0700 2014

線程生命周期

1、線程的創建可以使用Thread.new,同樣可以以同樣的語法使用Thread.start 或者Thread.fork這三個方法來創建線程。

2、創建線程后無需啟動,線程會自動執行。

3、Thread 類定義了一些方法來操控線程。線程執行Thread.new中的代碼塊。

4、線程代碼塊中最后一個語句是線程的值,可以通過線程的方法來調用,如果線程執行完畢,則返回線程值,否則不返回值直到線程執行完畢。

5、Thread.current 方法返回表示當前線程的對象。 Thread.main 方法返回主線程。

6、通過 Thread.Join 方法來執行線程,這個方法會掛起主線程,直到當前線程執行完畢。


線程狀態

線程有5種狀態:

線程狀態返回值
Runnablerun
SleepingSleeping
Abortingaborting
Terminated normallyfalse
Terminated with exceptionnil

線程和異常

當某線程發生異常,且沒有被rescue捕捉到時,該線程通常會被無警告地終止。但是,若有其它線程因為Thread#join的關系一直等待該線程的話,則等待的線程同樣會被引發相同的異常。

begin
  t = Thread.new do
    Thread.pass    # 主線程確實在等join
    raise "unhandled exception"
  end
  t.join
rescue
  p $!  # => "unhandled exception"
end

使用下列3個方法,就可以讓解釋器在某個線程因異常而終止時中斷運行。

  • 啟動腳本時指定-d選項,并以調試模時運行。
  • Thread.abort_on_exception設置標志。
  • 使用Thread#abort_on_exception對指定的線程設定標志。

當使用上述3種方法之一后,整個解釋器就會被中斷。

t = Thread.new { ... }
t.abort_on_exception = true

線程同步控制

在Ruby中,提供三種實現同步的方式,分別是:

1. 通過Mutex類實現線程同步

2. 監管數據交接的Queue類實現線程同步

3. 使用ConditionVariable實現同步控制

通過Mutex類實現線程同步

通過Mutex類實現線程同步控制,如果在多個線程鐘同時需要一個程序變量,可以將這個變量部分使用lock鎖定。 代碼如下:

#encoding:gbk
require "thread"
puts "Synchronize Thread"

@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

sleep 1
ticket1.join
ticket2.join

輸出結果如下:

Synchronize Thread
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets

除了使用lock鎖定變量,還可以使用try_lock鎖定變量,還可以使用Mutex.synchronize同步對某一個變量的訪問。

監管數據交接的Queue類實現線程同步

Queue類就是表示一個支持線程的隊列,能夠同步對隊列末尾進行訪問。不同的線程可以使用統一個對類,但是不用擔心這個隊列中的數據是否能夠同步,另外使用SizedQueue類能夠限制隊列的長度

SizedQueue類能夠非常便捷的幫助我們開發線程同步的應用程序,應為只要加入到這個隊列中,就不用關心線程的同步問題。

經典的生產者消費者問題:

#!/usr/bin/ruby

require "thread"
puts "SizedQuee Test"

queue = Queue.new

producer = Thread.new do
     10.times do |i|
          sleep rand(i) # 讓線程睡眠一段時間
          queue << i
          puts "#{i} produced"
     end
end

consumer = Thread.new do
     10.times do |i|
          value = queue.pop
          sleep rand(i/2)
          puts "consumed #{value}"
     end
end

consumer.join

嘗試一下 ?


程序的輸出:

SizedQuee Test
0 produced
1 produced
consumed 0
2 produced
consumed 1
consumed 2
3 produced
consumed 34 produced

consumed 4
5 produced
consumed 5
6 produced
consumed 6
7 produced
consumed 7
8 produced
9 produced
consumed 8
consumed 9

線程變量

線程可以有其私有變量,線程的私有變量在線程創建的時候寫入線程。可以被線程范圍內使用,但是不能被線程外部進行共享。

但是有時候,線程的局部變量需要別別的線程或者主線程訪問怎么辦?ruby當中提供了允許通過名字來創建線程變量,類似的把線程看做hash式的散列表。通過[]=寫入并通過[]讀出數據。我們來看一下下面的代碼:

#!/usr/bin/ruby

count = 0
arr = []

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

arr.each {|t| t.join; print t["mycount"], ", " }
puts "count = #{count}"

以上代碼運行輸出結果為:

8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10

主線程等待子線程執行完成,然后分別輸出每個值。 。


線程優先級

線程的優先級是影響線程的調度的主要因素。其他因素包括占用CPU的執行時間長短,線程分組調度等等。

可以使用 Thread.priority 方法得到線程的優先級和使用 Thread.priority= 方法來調整線程的優先級。

線程的優先級默認為 0 。 優先級較高的執行的要快。

一個 Thread 可以訪問自己作用域內的所有數據,但如果有需要在某個線程內訪問其他線程的數據應該怎么做呢? Thread 類提供了線程數據互相訪問的方法,你可以簡單的把一個線程作為一個 Hash 表,可以在任何線程內使用 []= 寫入數據,使用 [] 讀出數據。

athr = Thread.new { Thread.current["name"] = "Thread A"; Thread.stop }
bthr = Thread.new { Thread.current["name"] = "Thread B"; Thread.stop }
cthr = Thread.new { Thread.current["name"] = "Thread C"; Thread.stop }
Thread.list.each {|x| puts "#{x.inspect}: #{x["name"]}" }

可以看到,把線程作為一個 Hash 表,使用 [] 和 []= 方法,我們實現了線程之間的數據共享。


線程互斥

Mutex(Mutal Exclusion = 互斥鎖)是一種用于多線程編程中,防止兩條線程同時對同一公共資源(比如全局變量)進行讀寫的機制。

不使用Mutax的實例

#!/usr/bin/ruby
require '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
sleep 1
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

以上實例運行輸出結果為:

count1 :  9712487
count2 :  12501239
difference : 0

使用Mutax的實例

#!/usr/bin/ruby
require 'thread'
mutex = Mutex.new

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      mutex.synchronize do
         count1 += 1
         count2 += 1
      end
    end
end
spy = Thread.new do
   loop do
       mutex.synchronize do
          difference += (count1 - count2).abs
       end
   end
end
sleep 1
mutex.lock
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

以上實例運行輸出結果為:

count1 :  1336406
count2 :  1336406
difference : 0

死鎖

兩個以上的運算單元,雙方都在等待對方停止運行,以獲取系統資源,但是沒有一方提前退出時,這種狀況,就稱為死鎖。

例如,一個進程 p1占用了顯示器,同時又必須使用打印機,而打印機被進程p2占用,p2又必須使用顯示器,這樣就形成了死鎖。

當我們在使用 Mutex 對象時需要注意線程死鎖。

實例

#!/usr/bin/ruby
require 'thread'
mutex = Mutex.new

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...)
關閉
程序員人生
主站蜘蛛池模板: 波多野结衣一区二区三区88 | 亚洲xxx视频 | 国产精品18久久久久网站 | 视频一区二区精品的福利 | 五月婷婷综合在线视频 | 国产欧美另类久久精品91 | 国产无限资源在线观看 | 磁力天堂网在线资源www | 日韩性生活视频 | 国产18到20岁美女毛片 | 国产在线精品一区二区三区 | 久久精品综合一区二区三区 | 性黑人| 欧美性猛交xxxx乱大交中文 | 一区二区三区高清在线观看 | 羞羞视频免费看网站 | 老司机一级片 | 在线碰碰视频在线观看 | 最近中文字幕高清中文字幕在线看 | 免费一级淫片aa | 亚洲欧洲一区二区三区 | 免费看羞羞动漫视频网站 | 亚洲黄色在线观看网站 | 国产丝袜福利视频在线播放 | 亚洲 欧美 字幕 一区 在线 | 免费播放春色aⅴ视频 | 欧美xx网站| 天堂一码二码专区 | 日本在线无 | 亚洲精品456播放 | 伊人tv| 泰国一级毛片aaa下面毛多 | 欧美亚洲日本一区二区三区浪人 | 国产精品一页 | 在线观看国内自拍 | 免费看视频| 国产精品久久现线拍久青草 | 性加拿大高清xxxxx | 天堂伊人网 | 亚洲免费成人在线 | 亚洲精品在线观看视频 |