Ich habe ein Ruby-Skript-Array, wenn jedes Element verarbeitet werden muss:
threads = []
elemets.each do |element|
threads.push(Thread.new{process(element)}}
end
threads.each { |aThread| aThread.join }
Aufgrund von Ressourcenbeschränkungen funktioniert das Skript jedoch optimal, wenn nicht mehr die vier Elemente gleichzeitig verarbeitet werden.
Nein, ich weiß, ich kann jede Schleife ausgeben und eine Variable verwenden, um 4 Elemente zu zählen. Warten Sie dann, aber gibt es eine coolere Ruby-Methode, um dies zu tun?
Wenn ich Sie richtig gelesen habe, möchten Sie nicht mehr als 4 Threads gleichzeitig verarbeiten.
Klingt für mich so, als sollten Sie nur 4 Threads starten und alle aus einer gemeinsam genutzten Warteschlange (Teil der Standard-Thread-Bibliothek) lesen lassen, um die Elemente zu verarbeiten.
Sie können die Threads beenden lassen, wenn die Warteschlange leer ist.
Wenn Sie das Array in 4 gleiche Arrays aufteilen und jeder Thread 1/4 der Elemente verarbeitet, wird davon ausgegangen, dass jedes Element zur gleichen Zeit verarbeitet wird. Wenn einige länger dauern als andere, werden einige Ihrer Threads vorzeitig beendet.
Bei Verwendung einer Warteschlange stoppt kein Thread, bis die gemeinsam genutzte Warteschlange leer ist. Ich denke, dies ist eine effizientere Lösung.
Hier ist ein Arbeitsprogramm, das auf Ihrem Code basiert, um zu demonstrieren:
require 'thread' elements = [1,2,3,4,5,6,7,8,9,10] def process(element) puts "working on #{element}" sleep rand * 10 end queue = Queue.new elements.each{|e| queue << e } threads = [] 4.times do threads << Thread.new do while (e = queue.pop(true) rescue nil) process(e) end end end threads.each {|t| t.join }
quelle
ArgumentError: tried to create Proc object without a block
while (e = queue.pop(true) rescue nil)
2.3.1
. Ich habe es innerhalb einer Rake-Aufgabe in Rails ausgeführt, daher ist es durchaus möglich, dass es anderswo einen Konflikt gibt.Sie sind sich nicht sicher, ob die folgende Variante nur als "Variable zum Zählen von 4 Elementen" gilt oder als cool angesehen werden kann, aber Sie erhalten ein Array in Slices mit einer Größe von nicht mehr als 4 Elementen:
x = (1..10).to_a 0.step(x.size - 1, 4) do |i| # Choose one p x.slice(i, 4) p x[i, 4] end
quelle
In Schienen kann eine besser lesbare Form verwendet werden
in_groups_of
arr= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] arr.in_groups_of(4, false) {|a| p a}
Ergebnis:
[1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11]
Die letzte Zeile enthält nur 3 Elemente, da wir false in angegeben haben
in_group_of
. Wenn Sie null oder einen anderen Wert möchten, können Sie false durch diesen Wert ersetzen.quelle
in_groups_of
ist eine Rails-Methode, funktioniert nicht mit einfachem RubinJa, aber Sie müssen einige Methoden überschreiben. Der übliche Ansatz besteht darin, '/' für Folgendes zu überschreiben
Array
:class Array def / len a = [] each_with_index do |x,i| a << [] if i % len == 0 a.last << x end a end end
Und mit dieser Definition können Sie jetzt ganz einfach Folgendes tun:
foo = [1,2,3,4,5,6] foo / 2 # Result is [[1,2], [3,4], [5,6]]
quelle
/
und nicht%
? Was ist, wenn ein anderer Entwickler (oder ich, der dies implementiert hat) in ein oder zwei Jahren vorbeikommt und den Code verstehen möchte und fragt: "Was zum Teufel bedeutet eineArray
durch eine Zahl geteilte Zahl tatsächlich?"