«В информатике, поток исполнения является наименьшим последовательность запрограммированных инструкций, которые могут управляться независимо друг от друга с помощью операционной системы планировщика. Поток представляет собой процесс, легкий вес.»
irb(main):001:0> def calculate_sum(arr)
irb(main):002:1> sleep(2)
irb(main):003:1> sum = 0
irb(main):004:1> arr.each do |item|
irb(main):005:2* sum += item
irb(main):006:2> end
irb(main):007:1> sum
irb(main):008:1> end
=> :calculate_sum
irb(main):009:0>
irb(main):010:0* @items1 = [12, 34, 55]
=> [12, 34, 55]
irb(main):011:0> @items2 = [45, 90, 2]
=> [45, 90, 2]
irb(main):012:0> @items3 = [99, 22, 31]
=> [99, 22, 31]
irb(main):013:0>
irb(main):014:0* threads = (1..3).map do |i|
irb(main):015:1* Thread.new(i) do |i|
irb(main):016:2* items = instance_variable_get("@items#{i}")
irb(main):017:2> puts "items#{i} = #{calculate_sum(items)}"
irb(main):018:2> end
irb(main):019:1> end
=> [#<Thread:[email protected](irb):15 run>, #<Thread:[email protected](irb):15 run>, #<Thread:[email protected](irb):15 run>]
irb(main):020:0> threads.each {|t| t.join}
items3 = 152
items2 = 137
items1 = 101
=> [#<Thread:[email protected](irb):15 dead>, #<Thread:[email protected](irb):15 dead>, #<Thread:[email protected](irb):15 dead>]
irb(main):021:0>
Это базовый пример потоковой обработки процесса в Ruby. У вас есть основной метод calculate_sum
, который принимает массив в качестве аргумента @item1, @item2, @item3
. Оттуда вы делаете три потока threads = (1..3)
, сопоставляете их в свою собственную переменную .map do |i|
и запускаете новый экземпляр Thread
с переменной, на которую был нарисован нить, Thread.start(i)
.
Отсюда вы создаете переменную элемента, которая равна переменной экземпляра items = instance_variable_get(<object>)
, выводя результат вычисления, .
Как видите, потоки начинают работать одновременно => [#<Thread:[email protected](irb):15 run>, #<Thread:[email protected](irb):15 run>, #<Thread:[email protected](irb):15 run>]
. Все потоки выполняются путем вызова каждого потока и объединения их threads.each {|t| t,join}
.
Последний раздел является самым важным, все потоки выполняются и умирают одновременно, если поток имеет очень длительный процесс, который поток должен заканчиваться до завершения программы. Пример:
irb(main):023:0> Thread.new do
irb(main):024:1* puts t
irb(main):025:1> Thread.new do
irb(main):026:2* sleep(5)
irb(main):027:2> puts h
irb(main):028:2> end
irb(main):029:1> end
=> #<Thread:[email protected](irb):23 run>
irb(main):030:0> hello
goodbye
Вторая нить никогда не выходит, поэтому она будет продолжать работать, пока вы не сократите выполнение.
В главном примере конец имеет => [#<Thread:[email protected](irb):15 dead>, #<Thread:[email protected](irb):15 dead>, #<Thread:[email protected](irb):15 dead>]
, потому что все потоки завершают процесс и немедленно выходят. Для завершения моего процесса вам нужно будет предоставить exit
для второго потока.
Надеюсь, это ответит на ваши вопросы.
Что значит потокобезопасный, у Ruby не было бы функции «Thread», если бы было небезопасно вставлять ...? – 13aal
Я имел в виду, когда я читал и обновлял локальную переменную в нескольких потоках, не должен отличаться результат? – Abhishek
Интересно, как порядок применения атомной операции 'succ' к' Integer' может повлиять на результат? – mudasobwa