Le mécanisme de cooordination des threads est particulièrement utile dans un système Producteur/Consommateur. Par exemple, un producteur fabrique des articles pendant que les consommateurs attendent de les acquérir. Lorsqu'il y a suffisamment d'articles, les consommateurs peuvent acheter ces articles tandis que le producteur attend les premiers résultats des ventes. Lorsqu'un épuisement des articles survient, alors les consommateurs attendent de nouveau que le producteur génère une nouvelle série d'articles.
import java.util.ArrayList; public class Coordination { public Produits produits; public static void main(String[] args) { Coordination coord = new Coordination(); coord.produits = new Produits(); Producteur producteur = new Producteur(coord.produits); for(int i = 0; i < 25; i++) { Consommateur consommateur = new Consommateur(coord.produits); consommateur.setName(String.valueOf((char)('A' + i))); consommateur.start(); } producteur.start(); while(producteur.isAlive()) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Producteur extends Thread { public Produits produits; public Producteur(Produits produits) { this.produits = produits; } public void run() { int nb = 0; while(true) { produits.ajouter(nb); System.out.println("PRODUCTION : " + produits.size() + " Numero " + nb + " à " + produits.size()); nb = produits.size(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consommateur extends Thread { public Produits produits; public Consommateur(Produits produits) { this.produits = produits; } public void run() { while(true) { if(produits.size() > 0) { Article article = (Article)produits.obtenir(); System.out.println("VENTE : " + article.toString() + " à " + this.toString()); } try { Thread.sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } } // Objet partagé entre les threads class Produits extends ArrayList { public synchronized void ajouter(int nb) { while(this.size() > 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); if(nb == 0) nb = 10; else nb *= 2; for (int i = 0; i < nb; i++) { Article article = new Article(nb == 10 ? i : nb + i, 100, "lampe"); super.add(article); } } public synchronized Article obtenir() { while(this.size() == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); Article article = (Article)this.get(0); this.remove(0); return article; } } class Article { private int numero; private double prix; private String designation; public Article(int reference, double prix, String designation) { this.numero = reference; this.prix = prix; this.designation = designation; } public String toString() { StringBuffer res = new StringBuffer("["); res.append(this.numero); res.append(", "); res.append(this.prix); res.append(", "); res.append(this.designation); return res.append("]").toString(); } }