Vous disposez d'un module Java conçu pour gérer des tâches périodiques :
class SéquenceOrdonnancée {
public void phaseUn() {
for (int i = 0; i < n; i++) {
System.out.print("foo");
}
}
public void phaseDeux() {
for (int i = 0; i < n; i++) {
System.out.print("bar");
}
}
}
Deux instances Thread manipuleront simultanément un même objet SéquenceOrdonnancée. La première instanciation appellera phaseUn() tandis que la seconde invoquera phaseDeux(). Il est impératif de modifier l'implémentation afin de garentir l'émission de la chaîne "foobar" exactement n fois.
Traietments types :
- Paramètre
n = 1→ Résultat"foobar" - Paramètre
n = 4→ Résultat"foobarfoobarfoobarfoobar"
Cadrage technique : 1 ≤ n ≤ 1000.
Filaire bloquant (BlockingQueue)
class SéquenceOrdonnancée {
private final int cycleMax;
private final BlockingQueue<Void> mémoireA = new LinkedBlockingQueue<>(1);
private final BlockingQueue<Void> mémoireB = new LinkedBlockingQueue<>(1);
public SéquenceOrdonnancée(int itérations) {
this.cycleMax = itérations;
mémoireB.offer(null); // Amorçage pour initier le flux par la phase A
}
public void exécuterPhaseUn(Runnable tacheA) throws InterruptedException {
for (int cpt = 0; cpt < cycleMax; cpt++) {
mémoireA.take();
tacheA.run();
mémoireB.put(null);
}
}
public void exécuterPhaseDeux(Runnable tacheB) throws InterruptedException {
for (int cpt = 0; cpt < cycleMax; cpt++) {
mémoireB.take();
tacheB.run();
mémoireA.put(null);
}
}
}
Verrou réentrant et point de condition (ReentrantLock + Condition)
class SéquenceOrdonnancée {
private final int limiteCycles;
public SéquenceOrdonnancée(int répétitions) {
this.limiteCycles = répétitions;
}
private final ReentrantLock cadenas = new ReentrantLock();
private final Condition transition = cadenas.newCondition();
private volatile boolean prioritéPhaseA = true;
public void routageA(Runnable jobA) throws InterruptedException {
for (int idx = 0; idx < limiteCycles; idx++) {
cadenas.lock();
try {
while (!prioritéPhaseA) {
transition.await();
}
jobA.run();
prioritéPhaseA = false;
transition.signal();
} finally {
cadenas.unlock();
}
}
}
public void routageB(Runnable jobB) throws InterruptedException {
for (int idx = 0; idx < limiteCycles; idx++) {
cadenas.lock();
try {
while (prioritéPhaseA) {
transition.await();
}
jobB.run();
prioritéPhaseA = true;
transition.signal();
} finally {
cadenas.unlock();
}
}
}
}
Synchronisation intrinsèque, booléen de contrôle et notification
class SéquenceOrdonnancée {
private final int seuilRépétition;
private volatile boolean activerPhaseA = true;
private final Object verrouPartagé = new Object();
public SéquenceOrdonnancée(int total) {
this.seuilRépétition = total;
}
public void canalA(Runnable actionA) throws InterruptedException {
for (int i = 0; i < seuilRépétition; i++) {
synchronized (verrouPartagé) {
while (!activerPhaseA) {
verrouPartagé.wait();
}
actionA.run();
activerPhaseA = false;
verrouPartagé.notifyAll();
}
}
}
public void canalB(Runnable actionB) throws InterruptedException {
for (int i = 0; i < seuilRépétition; i++) {
synchronized (verrouPartagé) {
while (activerPhaseA) {
verrouPartagé.wait();
}
actionB.run();
activerPhaseA = true;
verrouPartagé.notifyAll();
}
}
}
}
Gestion par Sémapohres
class SéquenceOrdonnancée {
private final int bouclesContrôle;
private final Semaphore permisA = new Semaphore(1);
private final Semaphore permisB = new Semaphore(0);
public SéquenceOrdonnancée(int compteurs) {
this.bouclesContrôle = compteurs;
}
public void fluxAlpha(Runnable tacheAlpha) throws InterruptedException {
for (int j = 0; j < bouclesContrôle; j++) {
permisA.acquire();
tacheAlpha.run();
permisB.release();
}
}
public void fluxBeta(Runnable tacheBeta) throws InterruptedException {
for (int j = 0; j < bouclesContrôle; j++) {
permisB.acquire();
tacheBeta.run();
permisA.release();
}
}
}
Boucle d'attente active avec cession de ressources CPU
class SéquenceOrdonnancée {
private final int maximumItérations;
public SéquenceOrdonnancée(int objectif) {
this.maximumItérations = objectif;
}
private volatile boolean droitPassageA = true;
public void traitementA(Runnable étapeA) throws InterruptedException {
int avancementA = 0;
while (avancementA < maximumItérations) {
if (droitPassageA) {
étapeA.run();
avancementA++;
droitPassageA = false;
} else {
Thread.yield();
}
}
}
public void traitementB(Runnable étapeB) throws InterruptedException {
int avancementB = 0;
while (avancementB < maximumItérations) {
if (!droitPassageA) {
étapeB.run();
avancementB++;
droitPassageA = true;
} else {
Thread.yield();
}
}
}
}