Si je comprends bien, vous voulez avoir au maximum 4 threads en cours d'exécution à la fois.
Pour moi, il semble que vous devriez lancer uniquement 4 threads et les faire tous lire à partir d'une file d'attente partagée (partie de la bibliothèque de threads standard) pour traiter les éléments.
Vous pouvez terminer les threads lorsque la file d'attente est vide.
Diviser le tableau en 4 tableaux égaux, et avoir chaque thread traiter 1/4 des éléments suppose que chaque élément est traité en même temps. Si certains prennent plus de temps que d'autres, certains de vos threads finiront plus tôt.
En utilisant une file d'attente, aucun thread ne s'arrête tant que la file d'attente partagée n'est pas vide, je pense donc que c'est une solution plus efficace.
Voici un programme fonctionnel basé sur votre code pour illustrer :
require 'thread'
elements = [1,2,3,4,5,6,7,8,9,10]
def process(element)
puts "en train de travailler sur #{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 }