(Maj du site : j’ai rajouté la possibilité de s’abonner aux nouveaux commentaires. Si quelqu’un utilise ce plugin, merci de me prévenir si il fonctionne correctement. :-) )

Imaginez que vous voulez créer un programme qui affiche votre dernier message twitter et la météo du jour. En procédure normale, le programme afficherait d’abord votre dernier twit, et ensuite la météo. Mais si vous avez un problème avec twitter (le serveur est down par exemple, un classique) et que votre twit ne s’affiche pas, le programme attend, et la météo ne s’affiche toujours pas. Il vaut mieux gérer séparément et indépendamment ces deux tâches.

On donc créer plusieurs tâches, appelées Thread (comme “fils conducteurs”). Ca va permettre le multi-tâches.

Thread

Les Thread sont des objets auxquels on passe un bloc de code qui est exécuté une ou plusieurs fois, à intervalles différents.

premier = Thread.new() do
iterateur = 0
while(iterateur < 3):
puts "Et de 1!"
sleep 3
iterateur += 1
end
end
 
second = Thread.new() do
iterateur2 = 0
while(iterateur2 < 3):
puts "Et de 2!"
sleep 5
iterateur2 += 1
end
end
 
premier.join()
second.join()
→ Et de 1!
Et de 2!
Et de 1!
Et de 2!
Et de 1!
Et de 2!

J’ai deux objets Thread: “premier” et “second”. Je le crée en appelant la méthode .new, suivi d’un bloc do/end. A l’intérieur, j’ai une boucle classique. Mais la particularité est là : il y a le mot sleep. Ca permet de mettre en pause le programme pendant quelques secondes.
Dans l’ordre j’ai :

  • mon Thread “premier” qui affiche “Et de 1!” aux secondes 0, 3 et 6.
  • mon Thread “second” qui affiche “Et de 2!” aux secondes 0 (juste après le Thread “premier”), 5 et 10.

Ca fait donc:
0sec : “premier” et “second”
1sec : pause
2sec : pause
3sec : “premier”
4sec : pause
5sec : “second”
6sec : “premier” (et terminé)
7sec : pause
8sec : pause
9sec : pause
10sec : “second” (et terminé)
11sec : pause
12sec : pause
13sec : pause
14sec : pause
15sec : pause
Le programme s’arrête parce que tous les Thread sont terminés. Attention : le programme dure 15 sec parce que l’intervalle se fait avant de repasser dans la boucle. Donc le second Thread attend 5 sec à la fin avant de se rendre compte qu’il ne peut plus repasser dans la boucle (parce que iterateur2 est alors égal à 3).

Ce qu’il faut comprendre, c’est que pendant que mon premier Thread se met en pause (mais continue à tourner), le second est lancé, et se met en pause à son tour pendant que le premier continue. Ils travaillent en parallèle pendant un certain temps.

Et là vous me demandez pourquoi j’ai appelé la méthode .join pour les deux Thread ? Ca permet 2 choses :

  • attendre que chaque Thread ait fini toutes ses boucles
  • de lier les threads entre eux (et attendre que celui qui dure le plus longtemps ait fini)

Si je mets :

  • 0 join : le programme passe une seule fois sur les deux Thread (procédure normale)
  • 1 join sur le premier : le programme dure 12 sec
  • 1 join sur le second : le programme dure 15 sec
  • 2 join : le programme dure 15 sec (parce que le plus long est le second)

Timeout

On peut aussi mettre un timeout : au lieu de mettre une boucle avec un itérateur, on définit en temps la durée du Thread.

mon_timeout = Thread.new() do
while(true):
puts "1 seconde de passée"
sleep 1
puts "1 autre seconde de passée"
sleep 1
end
end 
mon_timeout.join(4)1 seconde de passée
1 autre seconde de passée
1 seconde de passée
1 autre seconde de passée

Là, ma boucle est while(true) donc elle est infinie. Mais en paramètre de la méthode .join j’ai mis “4″, c’est à dire 4 sec. Mon Thread dure 4 sec quoiqu’il arrive.