खोज…


वाक्य - विन्यास

  • क्यू = क्यू। न्यू
  • q.push वस्तु
  • q << ऑब्जेक्ट # समान # पश के रूप में
  • q.pop # => वस्तु

मल्टीपल वर्कर्स वन सिंक

हम कई वर्कर्स द्वारा बनाए गए डेटा को इकट्ठा करना चाहते हैं।

सबसे पहले हम एक कतार बनाते हैं:

sink = Queue.new

फिर 16 श्रमिक सभी एक यादृच्छिक संख्या उत्पन्न करते हैं और इसे सिंक में धकेलते हैं:

(1..16).to_a.map do
  Thread.new do
    sink << rand(1..100)
  end
end.map(&:join)

और डेटा प्राप्त करने के लिए, एक कतार को एक सरणी में परिवर्तित करें:

data = [].tap { |a| a << sink.pop until sink.empty? }

वन सोर्स मल्टीपल वर्कर्स

हम डेटा को समानांतर में प्रोसेस करना चाहते हैं।

चलो कुछ डेटा के साथ स्रोत आबाद करें:

source = Queue.new
data = (1..100)
data.each { |e| source << e }

फिर डेटा को संसाधित करने के लिए कुछ कार्यकर्ता बनाएं:

(1..16).to_a.map do
  Thread.new do
    until source.empty?
      item = source.pop
      sleep 0.5
      puts "Processed: #{item}"
    end
  end
end.map(&:join)

एक स्रोत - कार्य की पाइपलाइन - एक सिंक

हम डेटा को समानांतर में संसाधित करना चाहते हैं और इसे अन्य श्रमिकों द्वारा संसाधित की जाने वाली रेखा के नीचे धकेल देते हैं।

चूंकि श्रमिक दोनों डेटा का उपभोग करते हैं और हमें दो कतारें बनानी होती हैं:

first_input_source = Queue.new
first_output_sink  = Queue.new
100.times { |i| first_input_source << i }

श्रमिकों की पहली लहर first_input_source से एक आइटम first_input_source , आइटम संसाधित करती है, और first_output_sink में परिणाम first_output_sink :

(1..16).to_a.map do
  Thread.new do
    loop do
      item = first_input_source.pop
      first_output_source << item ** 2
      first_output_source << item ** 3
    end
  end
end

श्रमिकों की दूसरी लहर अपने इनपुट स्रोत के रूप में first_output_sink का उपयोग first_output_sink और फिर दूसरी आउटपुट सिंक पर प्रक्रिया को पढ़ती है:

second_input_source = first_output_sink
second_output_sink  = Queue.new

(1..32).to_a.map do
  Thread.new do
    loop do
      item = second_input_source.pop
      second_output_sink << item * 2
      second_output_sink << item * 3
    end
  end
end

अब second_output_sink सिंक सिंक है, आइए इसे एक सरणी में second_output_sink :

sleep 5 # workaround in place of synchronization
sink = second_output_sink
[].tap { |a| a << sink.pop until sink.empty? }

एक कतार में डेटा धक्का - #push

q = Queue.new
q << "any object including another queue"
# or
q.push :data
  • कोई उच्च पानी का निशान नहीं है, कतारें अनंत रूप से बढ़ सकती हैं।
  • #push कभी ब्लॉक नहीं होता

एक कतार से डेटा खींचना - #pop

q = Queue.new
q << :data
q.pop #=> :data
  • #pop तब तक ब्लॉक रहेगा जब तक कि कुछ डेटा उपलब्ध नहीं है।
  • #pop को सिंक्रोनाइज़ेशन के लिए इस्तेमाल किया जा सकता है।

तुल्यकालन - समय में एक बिंदु के बाद

syncer = Queue.new

a = Thread.new do
  syncer.pop
  puts "this happens at end"
end

b = Thread.new do
  puts "this happens first"
  STDOUT.flush
  syncer << :ok
end

[a, b].map(&:join)

एक पंक्ति को एक सरणी में परिवर्तित करना

q = Queue.new
q << 1
q << 2

a = Array.new
a << q.pop until q.empty?

या एक लाइनर :

[].tap { |array| array < queue.pop until queue.empty? }

दो कतारें मिलाना

  • असीम रूप से अवरुद्ध होने से बचने के लिए, कतारों से पढ़ना थ्रेड मर्ज पर नहीं होना चाहिए।
  • तुल्यकालन से बचने के लिए या असीम रूप से एक कतार का इंतजार करते हुए, जबकि अन्य में डेटा होता है, कतारों से पढ़ना एक ही धागे पर नहीं होना चाहिए।

चलो दो कतारों को परिभाषित और आबाद करके शुरू करते हैं:

q1 = Queue.new
q2 = Queue.new
(1..100).each { |e| q1 << e }
(101..200).each { |e| q2 << e }

हमें एक और कतार बनाना चाहिए और इसमें अन्य थ्रेड्स से डेटा पुश करना चाहिए:

merged = Queue.new

[q1, q2].map do |q|
  Thread.new do
    loop do
      merged << q.pop
    end
  end
end

यदि आप जानते हैं कि आप पूरी तरह से दोनों कतारों का उपभोग कर सकते हैं (खपत की गति उत्पादन से अधिक है, तो आप रैम से बाहर नहीं निकलेंगे) एक सरल तरीका है:

merged = Queue.new
merged << q1.pop until q1.empty?
merged << q2.pop until q2.empty?


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow