2010-10-29 24 views
0

我正在用Ruby編寫一個應用程序,它爲每個新作業創建一個新的線程。所以這就像一個隊列管理器,在這裏我檢查了可以從數據庫啓動多少個線程。現在,當一個線程完成時,我想調用該方法來開始一個新的工作(即新線程)。我不想創建嵌套的線程,所以有什麼方法可以加入/終止/退出調用線程並將控制權交給主線程?爲了清楚情況,此時可以運行其他線程。Ruby線程傳遞控制到主

我試着簡單地加入調用線程,如果它不是主線程,我得到以下錯誤;

"thread 0x7f8cf8dcf438 tried to join itself" 

任何建議將不勝感激。

在此先感謝。

+0

這是否在重塑車輪?你可以使用許多現有的消息隊列之一嗎? – 2010-10-29 12:18:48

回答

0

我想提出兩個解決方案:

第一個是有效地加入一個線程,但加入必須從主線程調用(假設你從主啓動所有工作線程):

def thread_proc(s) 
    sleep rand(5) 
    puts "#{Thread.current.inspect}: #{s}" 
end 

strings = ["word", "test", "again", "value", "fox", "car"] 

threads = [] 
2.times { 
    threads << Thread.new(strings.shift) { |s| thread_proc(s) } 
} 

while !threads.empty? 
    threads.each { |t| 
    t.join 
    threads << Thread.new(strings.shift) { |s| thread_proc(s) } unless strings.empty? 
    threads.delete(t) 
    } 
end 

但該方法是一種低效的,因爲一遍遍創建線程導致內存和CPU開銷。

你應該更好地使用隊列同步重用線程池固定:

require 'thread' 

strings = ["word", "test", "again", "value", "fox", "car"] 

q = Queue.new 
strings.each { |s| q << s } 

threads = [] 
2.times { threads << Thread.new { 
    while !q.empty? 
    s = q.pop 
    sleep(rand(5)) 
    puts "#{Thread.current.inspect}: #{s}" 
    end 
}} 

threads.each { |t| t.join } 
0
t1 = Thread.new { Thread.current[:status] = "1"; sleep 10; Thread.pass; sleep 100 } 
t2 = Thread.new { Thread.current[:status] = "2"; sleep 1000 } 
t3 = Thread.new { Thread.current[:status] = "3"; sleep 1000 } 

puts Thread.list.map {|X| x[:status] } 
#=> 1,2,3 

Thread.list.each do |x| 
    if x[:status] == 2 
    x.kill # kill the thread 
    break 
    end 
end 

puts Thread.list.map {|X| x[:status] } 
#=> 1,3 

「主題:: PASS」將控制權交給調度器現在可以安排任何其他線程。線程自願放棄控制權交給調度 - 我們不能指定通過控制到一個特定的線程

「線程#殺」將殺死實例的線程

「主題::名單」將返回列表線程

線程由調度程序管理,如果要顯式控制然後檢出光纖。但它有一些問題,JRuby不支持光纖。

也檢出線程局部變量,它會幫助你傳遞線程的狀態或返回值,而不需要加入到線程中。

http://github.com/defunkt/resque對於一個隊列來說是一個不錯的選擇,請檢查一下。如果您要大量使用線程,請嘗試使用JRuby。它的好處是它將以紅寶石般的優點包裝Java線程。

+0

我還沒有看到第一個答案(輸入它,然後出去喝咖啡)。但是看到它,線程池是生產質量代碼的必需品。 – deepak 2010-11-01 05:56:57