@ -5,7 +5,7 @@ Elliott LE GUEHENNEC -- Yorick GEOFFRE
## 1. Simulation d'une patisserie
### A.
Le patron lecteur/rédacteur présente le problème plusieurs lecteurs peuvent lire la même donnée, et ne peuvent pas la modifier; alors que les pâtisseries appartiennent au seul client qui les consommera (et donc les modifiera).
Le patron lecteur/rédacteur présente le problème suivant : lorsqu'un lecteur lit la ressource, il la bloque et les rédacteurs ne peuvent pas la modifier. Or, dans notre configuration, il se peut que le `Client` doive attendre alors qu'il essaie d'obtenir sa `Patisserie`, mais il serait quand même en train de lire la file d'attente, empêchant ainsi le `Patissier` de réapprovisioner la file; c'est un deadlock.
### B.
L'exclusion mutuelle se produit lorsqu'un `Client` veut acheter une `Patisserie` alors qu'aucune n'est disponible. Lorsque cela se produit, la `Boulangerie` bloque le thread en attendant qu'un `Patissier` dépose une `Patisserie` dans la boulangerie, débloquant ainsi la demande du client. La `Boulangerie` débloque le thread correspondant et retourne la `Patisserie` désirée au client.
@ -16,17 +16,140 @@ La `Boulangerie` est donc le moniteur dans ce modèle, on l'utilise pour synchro
Pour lancer des threads, on a créé une class ThreadWeaver. On peut lui faire passer des `Runnable` avec `addRunners()`, puis on leur assigne un thread chacun avec `weave()`, avant de les lancer avec `run()`. Avec `recover()`, on attend que tous les threads se soient terminés, et avec `termina()`, on interrompt tous les threads restants en affichant une erreur.
Le code de cette classe est en bas de ce document
## 2. Simulation d'une patisserie avec collection ThreadSafe
Ici, la `ArrayBlockingQueue` devient le moniteur, car elle gère elle-même l'accès par exclusion mutuelle. Le client sera bloqué par la file, et attendra tant qu'il n'aura pas son code grâce à `ArrayBlockingQueue.take();`.
## Annexes
## 3. Fin de programme
## Code
### Le ThreadWeaver
```java
public class Patisserie {
public Patisserie() {
}
}
public class Gateau extends Patisserie {
public Gateau() {
}
}
public class Client implements Runnable {
protected final Boulangerie local;
public Client(Boulangerie b) {
local = b;
}
@Override
public void run() {
while(true) {
local.achete();
System.out.println("J'ai acheté ma patisserie");
try {
Thread.sleep(80);
} catch (InterruptedException e) {
break;
}
}
}
}
public class LimitedClient extends Client{
public LimitedClient(Boulangerie b) {
super(b);
}
@Override
public void run() {
while(true) {
local.achete();
System.out.println("J'ai acheté ma patisserie - Limited");
try {
Thread.sleep(80);
} catch (InterruptedException e) {
break;
}
}
}
}
public class Patissier implements Runnable {
public AtomicBoolean shouldRun = new AtomicBoolean(true);
private final Boulangerie local;
public Patissier(Boulangerie b) {
local = b;
}
@Override
public void run() {
while(shouldRun.get()) {
local.depose(new Patisserie());
System.out.println("J'ai produit ma patisserie");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
}
public class Boulangerie {
private final ArrayList<Patisserie> sweets = new ArrayList<>();