-
Cours :
- Notions programmation orientée objet et Java (pdf)
- Tests (pdf)
- Principes SOLID (pdf)
- Patrons de conception (pdf)
-
Planches de TD :
- TD 1 (pdf), Corrigé TD 1 (pdf)
- TD 2 (pdf), Corrigé TD 2 (pdf)
- TP 1 (pdf), Corrigé TP 1 (pdf)
Gestionnaire de processus
Gestionnaire de processus
On veut simuler (de façon très simplifiée) un gestionnaire de processus d’un système d’exploitation. Chaque processus possède un nom, un temps d’exécution prédéfini (en nombre de quantums de temps) et un état. Le gestionnaire de processus possède une liste de processus parmi lesquels il peut choisir le prochain à exécuter pendant un quantum de temps. Un processus peut avoir trois états qui dépendent des signaux reçus par le processus.
Classe Process
Les instances de Process
représentent des processus avec
un état et une durée d’exécution en quantum.
public class Process {
enum State { READY, RUNNING, BLOCKED}
private final String name;
private int timeLeft;
private State state = State.READY;
private int lastExecDate = 0;
public Process(String name, int duration) {
this.name = name;
this.timeLeft = duration;
}
public void execQuantum(int date) {
System.out.println(date + ":" + name);
--;
timeLeft= date;
lastExecDate }
public boolean isReady() {
return state == State.READY;
}
public boolean isRunning() {
return state == State.RUNNING;
}
public int getLastExecDate() {
return lastExecDate;
}
public String getName() {
return name;
}
public int getTimeLeft() {
return timeLeft;
}
public void handleSignal(Signal signal) {
switch (signal) {
case BLOCK -> {
if (state == State.RUNNING) {
System.out.println(name + " blocked");
= State.BLOCKED;
state }
}
case UNBLOCK -> {
if (state == State.BLOCKED) {
System.out.println(name + " unblocked");
= State.READY;
state }
}
case SLEEP -> {
if (state == State.RUNNING)
= State.READY;
state }
case AWAKE -> {
if (state == State.READY)
= State.RUNNING;
state }
}
}
}
Enum Signal
Cette énumération permet de représenter les différents types de signal qu’on peut envoyer à un processus.
public enum Signal { BLOCK, UNBLOCK, SLEEP, AWAKE}
Classe ProcessManager
Les instances de ProcessManager
possède une liste de
processus parmi lesquels il peut choisir le prochain à exécuter pendant
un quantum de temps.
public class ProcessManager {
private List<Process> processes = new ArrayList<>();
private int date = 0;
private Process running = null;
public void add(Process process) {
.add(process);
processesSystem.out.println(process.getName() + " new");
}
private Process selectNext() { // Selection par round robin (tourniquet)
Process candidate = null;
int lastDate = Integer.MAX_VALUE;
for(Process process : processes) {
int lastExecDate = process.getLastExecDate();
if(process.isReady() && lastExecDate < lastDate) {
= process;
candidate = lastExecDate;
lastDate }
}
return candidate;
}
public void exec(int nbQuantum) {
for(int i = 0; i < nbQuantum ; i++) {
Process candidate = selectNext();
switchRunningProcess(candidate);
execRunningProcessQuantum();
++;
date}
}
private boolean canExecRunningProcess() {
return running != null && running.isRunning();
}
private void switchRunningProcess(Process candidate) {
if (candidate == null) return;
if (running != null) running.handleSignal(Signal.SLEEP);
.handleSignal(Signal.AWAKE);
candidate= candidate;
running
}
private void execRunningProcessQuantum () {
if (!canExecRunningProcess())
return;
.execQuantum(date);
runningif (running.getTimeLeft() <= 0) {
.remove(running);
processes= null;
running }
}
}
Classe
AppProcessManager
Cette classe permet d’observer le comportement des classes précédentes en demandant l’exécution de la suite d’instructions suivante :
public class AppProcessManager {
public static void main(String[] args) {
Process p1 = new Process("p1", 5);
Process p2 = new Process("p2", 7);
Process p3 = new Process("p3", 4);
= new ProcessManager();
ProcessManager processManager .add(p1); //affiche "p1 new"
processManager.exec(1); // affiche "0:p1"
processManager.add(p2); // affiche "p2 new"
processManager.exec(2); // affiche "1:p2" puis "2:p1"
processManager.add(p3); // affiche "p3 new"
processManager.handleSignal("block"); // affiche "p1 blocked"
p1.exec(3); // affiche "3:p3", "4:p2", "5:p3"
processManager.handleSignal("unblock"); // affiche "p1 unblocked"
p1.exec(10); // affiche "6:p1", "7:p2", "8:p3", "9:p1", etc
processManager}
}
Questions
Question 1 : Il s’avère que d’autres types de processus peuvent exister (par exemple des processus avec différents niveaux de priorités). Selon cette constatation précise, quel principe SOLID a été violé et pourquoi ?
Question 2 : Par ailleurs, le gestionnaire de processus pourrait avoir une autre façon de sélectionner les prochains processus à exécuter et une autre façon d’exécuter un processus pendant un quantum de temps. Selon cette constatation précise, quel principe SOLID a été violé et pourquoi ?
Question 3 : Si on veut proposer de nouveaux états
pour les processus, il faut changer le contenu la classe
Process
. Selon cette constatation précise, quel
principe SOLID a été violé et pourquoi ?
Question 4 : On souhaite rajouter des processus qui
ne sont jamais censés s’arrêter (les processus “démons”). Or, la classe
Process
possède une méthode int getTimeLeft()
.
Selon cette constatation précise, quel principe SOLID a été violé et
pourquoi ?
Question 5 : Pour rajouter les processus démons
de la question précédente, on vous demande de rajouter des classes
AbstractProcess
, Daemon
et
FiniteProcess
de telle sorte à ce que Daemon
et FiniteProcess
étendent AbstractProcess
(cf. diagramme de classes ci-après). L’objectif est que
FiniteProcess
remplace la classe Process
et
que Daemon
permette de créer des processus démons. Pour
ceci AbstractProcess
contiendra une méthode abstraite
boolean isOver()
qui indique si le processus est
terminé.
Question 6 : Réécrire la classe
ProcessManager
pour qu’elle délègue la sélection de
processus à une instance d’une classe de l’interface
ProcessSelector
contenant l’unique méthode
Process selectNext(List<Process> processes)
(cf. le
diagramme ci-dessous).
Question 7 : Pour le moment, les processus définis ne peuvent être que dans trois états : ready, running ou blocked. Comme un processus peut habituellement être dans plus d’états (il existe neuf états de processus sous Unix), il faut prévoir l’ajout (ou le retrait) d’autres états dans des versions ultérieures du programme. Vous allez utiliser le patron de conception State pour définir les états possibles d’un processus ainsi que ses transitions. Dessinez le diagramme de classe correspondant à cette modification.
Question 8 : Donnez les modifications à faire dans le code pour obtenir la réorganisation du code que vous avez décrite pour la question précédente.
Question 9 : On souhaite rajouter de nouveaux processus avec différents niveaux de priorités allant de 1 à 10 et d’utiliser les priorités pour la sélection du processus à exécuter (par exemple en ne sélectionnant le prochain processus à exécuter uniquement parmi ceux de priorité maximale qui peuvent s’exécuter). Décrivez à l’aide d’un diagramme de classes la manière de réorganiser le code pour prendre compte cette modification tout en gardant la possibilité d’avoir un système de processus sans priorité.