2017-04-14 55 views
0

我正在編寫一個程序,它將執行一些檢查並通過puts輸出結果。我想用線程加速這個過程。但是,輸出包含不一致的新行。與Ruby線程和放入的輸出不一致

如何清理此輸出?

Ex。

> (1..99).each_with_object([]) {|i, threads| threads << Thread.new {sleep(rand 2) && puts(i)} }.each(&:join) 
7 
202535 
36605562 
7882 
8959958 
2826 

29 
433941 
445258 

69728063 
777975 



85496 

22 

14 
24 



3850 



9712 
9892 


47 

40 

71 
84 

94 
49 







1 
2 
152187131627234218194531535759 
305417 
34647448 
735111 
66684676 
838137 
6133 
679093 
917099 
3 






56 

32 


10 

6 















88 



86 

65 

回答

1

用鐵皮人的評論

使用更新print/printfputs,並提供新的行字符\n明確(因爲puts可以分開休息和其他線程寫入新行可能會跳入)。

(1..99).each_with_object([]) {|i, threads| threads << Thread.new {sleep(rand 2) && print("#{i}\n") } }.each(&:join) 
+3

答案並不是'printf'需要用來代替'puts',這就是'puts'需要輸出一個字符串,該字符串包含該行的所有內容,包括尾部的行尾,就像'printf'一樣。當它輸出到控制檯時將會有。 'puts'足夠聰明,可以在輸出值不存在的情況下添加尾隨的「\ n」,這就是其他線程跳入的位置。只要值已準備就緒,'print'也可以工作輸出。 –

+0

做一些測試我已經在我的用例中解決了'print'問題,因爲它似乎提供了一致結果的簡單語法。 – HarlemSquirrel

0

你的線程都共享資源:stdout。只要你有線程共享一個資源,你就需要確保你一次沒有多個資源訪問資源,否則你會看到干擾。

以下是解決這個問題的兩種方法。首先,您可以更改線程只返回一個值,然後做所有的打印算賬:

threads = (1..99).map {|i| Thread.new { sleep(rand 2) && i } } 
threads.each do |t| 
    t.join 
    puts t.value 
end 

這是在大約相同的速度,因爲它會掛在最慢的線程,如果你的線程都跑一個好方法(即使其他更快的線程已經完成)。

或者,使用互斥鎖來保護標準輸出。

mutex = Thread::Mutex.new 
(1..99).map do |i| 
    Thread.new { sleep(rand 2); mutex.synchronize { puts i } } 
end.each(&:join) 

這將讓每個線程獨立運行和打印。但是,如果你需要每個線程來進行大量的打印,那麼它就不是那麼好:它們越多地與互斥體作鬥爭,線程就越慢。