Rubyスレッド学習(一)


1つのプログラムには複数のプロセスが構成され、1つのプロセスには複数のスレッドが並列に実行されることも知られています.スレッドの並列実行は、プログラムの実行効率を向上させることができますが、複数のスレッドが1つのリソースを占有する可能性があるという危険もあります.ここではrubyを例にrubyにおけるスレッドの応用について述べる.
まず、簡単なプログラムから始め、プログラムは異なるウェブサイトに対してパラレルに要求を送信するプロセスを実現します.コードは次のとおりです.
require 'net/http'

pages = %w(www.iteye.com www.csdn.net www.sina.com.cn www.google.cn)
threads = []

for page in pages
  threads << Thread.new(page) do |url|
    h = Net::HTTP.new(url, 80)
    puts "The URL is #{url} "
    resp = h.get('/', nil)
    puts "The #{url} response : #{resp.message}"
  end
end

threads.each { |t|t.join  }

このセグメントプログラムはProgramming Rubyから引用され,プログラムにはウェブサイトのリスト配列が提供され,配列から対応するウェブサイトが同時に要求される.%wに戸惑う人もいるかもしれませんが、%wは自動的に括弧の後ろの文字列をスペースで分割し、配列に保存します.どうですか、ルビーはsexでしょう、たくさんの「」の悩みを省きました.
我々はnewでスレッドを作成します.サイトリストのアドレスをパラメータとしてスレッドに渡します.ここで問題なのは、なぜアドレスをblock(net)に直接伝えないのかということです.ここではスレッドのグローバル変数と局所変数の概念にかかわる.考えてみてください.もし私たちがnetモジュールにアドレスを直接渡すと、スレッド1が実行完了していない間にスレッド2が起動し、pageに値を割り当て直した場合、このときのスレッド1はpageを使用しています.エラーはこのとき発生し,このようなエラーはスレッド並列では発見しにくいことが多い.変数をスレッドにプライベート化することです.ここでは,スレッドに渡される変数ごとにurlなしを私有化し,現在のスレッドでのみ有効とする.これにより、スレッド間のグローバル変数共有の問題がうまく解決されます.
threads.each { |t|t.join  }

このコードに気づいたかもしれませんが、rubyでは、プログラムが終了すると、スレッドの状態にかかわらず、すべてのスレッドが殺されます.特定のスレッドの終了を待つためにThread#joinメソッドを呼び出します.joinを呼び出すスレッドは、指定したスレッドが終了するまでブロックされるため、すべてのスレッドに対してjoin操作を実行し、プログラムが終了する前にすべてのスレッドを実行することを保証できます.
前述したように、スレッドにはプライベート変数があり、スレッドのプライベート変数はスレッドの作成時にスレッドに書き込まれます.スレッド範囲内で使用できますが、スレッド外部で共有することはできません.しかし、スレッドのローカル変数が他のスレッドやプライマリスレッドにアクセスする必要がある場合はどうすればいいですか?rubyでは,名前によるスレッド変数の作成を許可し,同様にスレッドをhash式のハッシュリストと見なす.[]=書き込み、[]でデータを読み出します.次のコードを見てみましょう.
#     

count = 0
threads =[]
10.times do |i|
  threads[i] = Thread.new  do
    sleep(rand(0.1))
    Thread.current["myvalue"] =count  #        
    count += 1
  end
end

threads.each { |t| t.join; puts t["myvalue"] }
私たちは前のプログラムと同じように、それぞれ10個のスレッドを作成し、現在のスレッドに値を割り当て、myvalueで識別し、最後にスレッドの外部でmyvalueの表示でデータを読み取ることができます.では、スレッドの最初のステップはここまでです.明日へ続く