Le problème traité ici est de type producteur-consommateur. Un ensemble de personnes dispose d'une seule boîte aux lettres, mais cette boîte présente la particularité de ne pouvoir contenir qu'une seule lettre : dès qu'elle contient une lettre, elle est considérée comme pleine. Des personnes, que l'on appelle producteurs, peuvent y déposer une lettre (si la boîte n'est pas pleine) et d'autres personnes, appelées consommateurs, peuvent y retirer une lettre (si la boîte est pleine). Les lettres ont un auteur mais pas de destinataire particulier, n'importe quel consommateur peut retirer une lettre. Chaque personne est un thread. Il y a dans notre programme deux producteurs et deux consommateurs. Chaque producteur doit déposer successivement deux lettres portant son nom et le numéro d'ordre de son courrier ; chaque consommateur doit retirer deux lettres.
Une classe BoiteAuxLettres modélise la boîte aux lettres ; deux méthodes y sont définies : les méthodes deposer et retirer. C'est la boîte aux lettres qui gère la synchronisation et la coordination de telle sorte que :
Voici l'exemple proposé.
import java.util.*;
class BoiteAuxLettres
{
private boolean plein = false;
private String lettre;
synchronized void deposer(String lettre)
{
try
{
while (plein) wait();
}
catch(InterruptedException exc) {}
this.lettre=lettre;
System.out.println("depot de : " + lettre);
plein = true;
notify();
}
synchronized String retirer(String nomConso)
{
try
{
while (!plein) wait();
}
catch(InterruptedException exc) {return null;}
System.out.println(nomConso + " lit : " + lettre);
plein = false;
notify();
return lettre;
}
}
class Producteur extends Thread
{
BoiteAuxLettres boite;
String nom;
Random alea;
Producteur(BoiteAuxLettres boite, String nom, Random alea)
{
this.boite = boite;
this.nom = nom;
this.alea = alea;
}
public void run()
{
for (int i = 0; i < ProdCons.TOTAL; i++)
{
try
{
sleep(Math.abs(alea.nextInt())%1000);
}
catch(InterruptedException e)
{
System.out.println("interruption");
}
boite.deposer(nom + ", lettre "+ (i + 1));
}
}
}
class Consommateur extends Thread
{
BoiteAuxLettres boite;
String nom;
Random alea;
Consommateur(BoiteAuxLettres boite, String nom, Random alea)
{
this.boite=boite;
this.nom=nom;
this.alea=alea;
}
public void run()
{
for (int i=0;i<ProdCons.TOTAL;i++)
{
try
{
sleep(Math.abs(alea.nextInt())%1000);
}
catch(InterruptedException e)
{
System.out.println("interruption");
}
boite.retirer(nom);
}
}
}
class ProdCons
{
final static int TOTAL=3;
public static void main(String[] argv)
{
BoiteAuxLettres boite = new BoiteAuxLettres();
Random alea=new Random();
new Producteur(boite,"David", alea).start();
new Producteur(boite,"Antoine", alea).start();
new Consommateur(boite,"Sophie", alea).start();
new Consommateur(boite,"Marie", alea).start();
}
}
On a obtenu :
:
depot de : Antoine, lettre 1
Marie lit : Antoine, lettre 1
depot de : David, lettre 1
Sophie lit : David, lettre 1
depot de : Antoine, lettre 2
Sophie lit : Antoine, lettre 2
depot de : Antoine, lettre 3
Sophie lit : Antoine, lettre 3
depot de : David, lettre 2
Marie lit : David, lettre 2
depot de : David, lettre 3
Marie lit : David, lettre 3
Vous pouvez récupérer le programme d'exemple.