:: Enseignements :: ESIPE :: E4INFO :: 2015-2016 :: Java Réseau I - Concurrence et E/S ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Examen de concurrence sur table - Session de Juillet |
Vous avez droit à aucun document.
Exercice 1 - Questions de cours (7)
Répondez aux questions suivantes en deux ou trois phrases, pas plus,
et SVP répondez à la question pas au mot-clef.
-
Qu'est ce qu'une classe thread-safe ?
-
A quoi servent les classes du package java.util.concurrent.atomic.
Quelles sont les avantages/inconvénients par rapport à l'utilisation
de moniteur avec le bloc synchronized.
-
Le code suivant a t'il un problème de publication ?
public class Point {
private volatile int x;
private long y;
public Point(int x, long y) {
this.x = x;
this.y = y;
}
}
Si oui, pourquoi ? si non pourquoi ?
-
Pourquoi un notify sur un objet doit être appelé
dans un bloc synchronized sur le même objet.
Quelle serait le ou les problèmes si Java n'imposait pas cette restriction.
-
Quelles sont les deux raisons pour lesquels il faut mettre les appels
à wait à l'intérieur d'une boucle while.
-
Quel est l'intérêt d'utiliser un pool de threads (on parle d'executor en Java)
par rapport à gérer des threads à la main ?
-
A quoi sert l'interface java.util.concurrent.Future.
Exercice 2 - Flux (7)
La classe Flux permet de connecter un ensemble de puits (sink en anglais) de données à un ensemble
de sources de données. Un puit de données consomme des valeurs alors qu'une source de données produit des données.
La méthode sink permet d'enregistrer un puit de donnée, une méthode (une lambda) qui sera exécutée
à chaque fois qu'une donnée est produite.
La méthode source permet de définir une source de donnée, les données sont envoyées en appelant
autant de fois que nécessaire la méthode accept sur l'accepteur (acceptor) pris en paramètre.
Les données commence à être envoyée dès l'appel de la méthode source.
public class Flux<T> {
private final ArrayList<Consumer<? super T>> consumers = new ArrayList<>();
public void sink(Consumer<? super T> consumer) {
consumers.add(consumer);
}
public void source(Consumer<Consumer<? super T>> acceptorConsumer) {
acceptorConsumer.accept(t -> {
for(Consumer<? super T> consumer: consumers) {
consumer.accept(t);
}
});
}
}
Voici un exemple de main de test qui affiche les valeurs de 0 à 9 à la fois sur l'entré standard
et sur la sortie standard.
public static void main(String[] args) {
Flux<Integer> flux = new Flux<>();
flux.sink(System.out::println);
flux.sink(System.err::println);
flux.source(acceptor -> {
for(int i= 0; i < 10; i++) {
acceptor.accept(i);
}
});
}
-
Indiquer le code d'un main qui créé une thread pour envoyer les valeurs de 0 à 9
à travers l'accepteur.
-
Pourquoi le code que vous avez écrit ne va pas fonctionner comme il devrait ?
Quel est le problème ?
-
En fait, si l'on veut que la classe Flux soit thread safe
(et ce pour n'importe quel main), il faut aussi régler le problème qui arrive
lorsque l'on utilise un seul puit avec deux sources différentes.
Quel est le problème ?
-
Indiquer un nouveau code pour la classe Flux qui rend la classe Flux
thread safe (c'est à dire qui rêgles les deux problèmes vu dans les deux questions précédentes)
en utilisant la syntaxe synchronized.
-
Indiquer un nouveau code pour la classe Flux qui la rend thread safe
mais cette fois en utilisant les ReentrantLock
-
Enfin, ici, il est possible d'avoir un code beaucoup plus efficace
en utilisant les collections concurrentes du package java.util.concurrent,
que doit on modifier dans la classe Flux dans ce cas et pourquoi ?
Exercice 3 - PermitPool (6)
On souhaite implanter une classe stockant un nombre de permis
définie lors de la création de l'objet
et permettant à des threads d'attraper (grab) plusieurs permis
puis de relacher (ungrab) le même nombre de permis.
Dans le cas ou un thread chercherait à prendre plus de permis que ce qui est
disponible, celle-ci sera mis en attente.
public class PermitPool {
/**
* Create a PermitPool with a maximum number of permits.
* @param maxPermits the maximum number of permits allowed to be grabbed by one thread
* if all other thread have not grab any permits.
*/
public PermitPool(int maxPermits) {
}
/**
* Try to grab some permits.
* This method may block if there is not enough permits in the permit pool
* @param permits number of permits to grab.
* @throws IllegalArgumentException if the number of permits is negative or zero
* or bigger than max permits.
* @throws IllegalStateException if the current thread has already grab some permits
* without releasing them with ungrab.
* @throws InterruptedException if the thread is interrupted
* while waiting to grab the permits.
*/
public void grab(int permits) throws InterruptedException {
}
/**
* Release the number of permits previously taken by grab.
* @throws IllegalStateException if the current thread doesn't hold any permits
(i.e. have not grab any permits before).
*/
public void ungrab() {
}
}
-
Donner le code la classe PermitPool.
© Université de Marne-la-Vallée