Salut tout le monde,
J'ai mis en place un système producteur-consommateur en Java, avec un tampon borné de 10 entiers implémenté à l'aide de la classe ConcurrentBuffer
. Cette dernière possède deux méthodes : une qui permet de déposer un entier, l'autre d'en retirer un (le plus vieux). Un délai de 1/100s est mis entre chaque opération.
Mon code compile, s'exécute bien et fait ce qu'il est censé faire ; cependant je voudrais être sûr que je n'ai pas fait une petite erreur…
J'ai donc en tout quatre classes :
Consommateur
;Producteur
;ConcurrentBuffer
;Launcher
Classes Consommateur
et Producteur
Les classes Consommateur
et Producteur
possèdent toutes deux un attribut d'instance de type ConcurrentBuffer
, donné lors de leur instanciation dans la classe Launcher
.
Consommateur
ne fait qu'appeler la méthode de ConcurrentBuffer
extrayant l'élément. De même, Producteur
ne fait qu'appeler la méthode ajoutant un élément (tout simplement 0
).
Code de Consommateur
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Consommateur extends Thread { private ConcurrentBuffer concurrent_buffer; public Consommateur(ConcurrentBuffer concurrent_buffer) { this.concurrent_buffer = concurrent_buffer; } public void run() { try { while (true) { concurrent_buffer.getOldest(); System.out.println("Le consommateur a retiré un élément."); Thread.sleep(100); } } catch(InterruptedException e) { System.out.println(e); } } } |
Code de Producteur
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Producteur extends Thread { private ConcurrentBuffer concurrent_buffer; public Producteur(ConcurrentBuffer concurrent_buffer) { this.concurrent_buffer = concurrent_buffer; } public void run() { try { while (true) { concurrent_buffer.push(0); System.out.println("Le producteur a placé un élément."); Thread.sleep(100); } } catch(InterruptedException e) { System.out.println(e); } } } |
Code de ConcurrentBuffer
ConcurrentBuffer
possède l'attribut d'instance array
(une ArrayList
) ainsi que trois autres attributs d'instance, des Semaphore
. L'idée est d'avoir un mutex (qui empêche le thread-producteur et le thread-consommateur de travailler au même instant T sur le ConcurrentBuffer
). Les deux autres Semaphore
permettent de borner l'ArrayList
du ConcurrentBuffer
: ainsi places_libres
est-il décrémenté (acquire()
) lorsque le thread-producteur travaille, et incrémenté (release()
) lorsque le thread-consommateur travaille. Inversement pour le Semaphore
nommé nombre_elements
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import java.util.ArrayList; import java.util.concurrent.Semaphore; public class ConcurrentBuffer { private ArrayList<Integer> array; private Semaphore mutex, places_libres, nombre_elements; public ConcurrentBuffer() { array = new ArrayList<Integer>(); this.mutex = new Semaphore(1); this.places_libres = new Semaphore(10); this.nombre_elements = new Semaphore(0); } public void push(int value_to_push) { try { places_libres.acquire(); mutex.acquire(); array.add(value_to_push); mutex.release(); nombre_elements.release(); } catch (InterruptedException e) { System.out.println(e); } } public void getOldest() { try { nombre_elements.acquire(); mutex.acquire(); array.remove(0); mutex.release(); places_libres.release(); } catch(InterruptedException e) { System.out.println(e); } } } |
Voilà. Si quelqu'un a le temps de vérifier que ce que j'ai fait est correct, ce serait vraiment cool !
Merci d'avance !