les Threads
Problématique
: Le perroquet et moi souhaitons bavarder en même temps
Source de BavarderEtLancerLePerroquet0.java
class BavarderEtLancerLePerroquet0
{
public static void main(String args[]) {
Perroquet0 perroquet = new Perroquet0("coco",4);
blabla();
blabla();
perroquet.run();
blabla();
for (int n=0; n<10; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
catch(InterruptedException e) {
System.out.println(e.getMessage());
System.exit(1);
}
blabla();
}
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet0
{
private String cri = null;
private int fois = 0;
public Perroquet0(String s, int i) {
cri = s;
fois = i;
}
/** methode de perroquet
* qui pourrait se nommer repeter
*/
public void run(){
for (int n=0; n<fois; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {
System.out.println(e.getMessage());
System.exit(1);
}
System.out.println(cri);
}
}
}
|
- Les lignes de la classe :
- sleep est une méthode de classe de Thread : "l'exécution
dort" durant tant de millisecondes ; en fait, l'éxécution
du présent code est suspendue pendant au moins le temps
indiqué, et pendant ce temps, le processeur fait autre
chose.
- ceci permet à notre bavardeur et
à notre perroquet d'avoir le temps de penser (en tout
respirer) entre 2 paroles.
- EXECUTION
blabla
blabla
coco
coco
coco
coco
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
|
|
- Les lignes de la classe :
- Malheureusement, le perroquet interrompt
le bavardeur qui ne "blablate" qu'après que
le perroquet ait fini.
- Ce que nous voudrions :
- le bavardeur "blablate"
- puis démarre le perroquet
- puis "blablater" en même
temps que le perroquet se répète
|
Multitâche
Source de BavarderEtLancerLePerroquet1.java
class BavarderEtLancerLePerroquet1
{
public static void main(String args[]) {
class BavarderEtLancerLePerroquet1
{
public static void main(String args[]) {
Perroquet1 objectPerroquet = new Perroquet1("coco",10);
Thread threadPerroquet = new Thread(objectPerroquet);
threadPerroquet.start();
for (int n=0; n<10; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
blabla();
}
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet1 implements Runnable
{
private String cri = null;
private int fois = 0;
public Perroquet1(String s, int i) {
cri = s;
fois = i;
}
public void run(){
for (int n=0; n<fois; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
System.out.println(cri);
}
}
}
|
- les lignes de la classe :
- La classe des objets "exécutables"
est Thread
- La méthode run du thread s'exécute
en même temps que les autres threads.
- Le lancement du thread se fait par l'appel
de la méthode start() : elle ne fait que déclancher
le démarrage du thread et (n'est pas bloquante dans le
thread appelant) n'attend pas la fin de l'exécution de
run.
- L'interface Runnable contient
essentiellemnt la méthode run. Elle permet à tout
objet d'avoir la fonctionnalité d'un thread.
- EXECUTION
coco
blabla
blabla
coco
blabla
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
blabla
blabla
coco
coco
coco
coco
|
 |
- le thread perroquet s'est bien exécuté
en même temps que le thread principal "bavardeur".
Thread
Source de BavarderEtLancerLePerroquet2.java
class BavarderEtLancerLePerroquet2
{
public static void main(String args[]) {
Perroquet2 perroquet = new Perroquet2("coco",10);
perroquet.start();
for (int n=0; n<10; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {}
blabla();
}
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet2 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet2(String s, int i) {
cri = s;
fois = i;
}
public void run(){
for (int n=0; n<fois; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {}
System.out.println(cri);
}
}
}
|
- EXECUTION
blabla
coco
coco
blabla
blabla
coco
coco
blabla
coco
blabla
coco
coco
blabla
coco
coco
blabla
blabla
coco
blabla
blabla
|
|
- start autorise le démarrage du
thread perroquet, mais pas forcément immédiatement.
- Thread :
- Le nom original était Thread of
control : un objet thread est un fil de contrôle, cad un
cheminement d'instruction d'un programme.
- C'est une classe :
- méthodes d'instance :
- run() est la méthode à redéfinir
pour y placer le fonctionnement du thread
- start() est une méthode autorisant
le démarrage du thread, donc l'exécution de run.
Elle retourne immédiatement à l'exécution
du thread appelant.
- méthode de classe :
- sleep(long nombreDeMillisecondes) suspend
l'exécution du thread; cette méthode est susceptible
de lever une exception quand le thread est interrompu (interrupt)
avant la fin du temps
perroquet
= null donc l'absence de référence sur un Thread
ne provoque pas la fin du thread par le garbage collector car
les threads sont "enregistrés" par un controlleur
d'exécution.
Cycle
de vie d'un thread
Source de BavarderEtLancerLePerroquet4.java
class BavarderEtLancerLePerroquet4
{
public static void main(String args[]) {
Perroquet4 perroquet = new Perroquet4("coco",5);
perroquet.start();
System.out.println("thread bavard : "
+ Thread.currentThread().getName());
for (int n=0; n<15; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
blabla();
}
System.out.println("thread perroquet isAlive : "
+ perroquet.isAlive());
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet4 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet4(String s, int i) {
cri = s;
fois = i;
}
public void run(){
System.out.println("thread perroquet : "
+ Thread.currentThread().getName());
for (int n=0; n<fois; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
System.out.println(cri);
}
}
}
|
- les lignes de la classe :
- la méthode isAlive() détermine
:
- si un thread est en train d'exécuter
sa méthode run
- s'il se trouve dans le court état
entre start et sa conséquence run
- s'il se trouve dans le court état
entre la fin de run et la constation par le système qu'il
est terminé !
- la méthode de classe currentThread()
donne un pointeur sur l'objet thread
qui appele cette méthode
- la méthode getName() donne le
nom du thread
- EXECUTION

thread bavard : main
thread perroquet : Thread-0
blabla
coco
coco
blabla
blabla
coco
blabla
coco
blabla
coco
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
thread perroquet isAlive : false
|
- Le thread "principal",
celui qui exécute main s'appelle main
- L'autre, celui du perroquet, a reçu
comme nom par défaut Thread-0
- Le cycle de vie d'un Thread illustre qu'il
peut être suspendu par :
- attente du délai suite à
un sleep
- une attente bloquante d'entrée-sortie
- une attente de synchronisation wait.
- l'état d'un thread peut être
précisée par l'appel à sa méthode
getState()
Les
propriétés des différents threads
Source de BavarderEtLancerLePerroquet5.java
class BavarderEtLancerLePerroquet5
{
public static void main(String args[]) {
Thread.currentThread().setName("bavard");
Perroquet5 perroquet = new Perroquet5("coco",15);
perroquet.start();
for (int n=0; n<5; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
blabla();
}
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet5 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet5(String s, int i) {
super("perroquet");
cri = s;
fois = i;
}
public void run(){
afficheThreads();
for (int n=0; n<fois; n++) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
System.out.println(cri);
}
afficheThreads();
}
private void afficheThreads() {
Thread[] tabThread = new Thread[Thread.activeCount()];
int nbrThread = Thread.enumerate(tabThread);
for (int i = 0; i < nbrThread ; i++)
System.out.println(i + "-ieme thread : "
+ tabThread[i].getName());
}
}
|
EXECUTION
0-ieme thread : bavard
1-ieme thread : perroquet
blabla
blabla
coco
blabla
coco
blabla
blabla
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
0-ieme thread : perroquet
1-ieme thread : DestroyJavaVM
|
|
- les lignes de la classe :
- la méthode setName(String nom)
permet de nommer le thread
- le constructeur offre la possibilité
de le nommer ainsi Thread(String nom)
- la méthode de classe activeCount()
donne le nombre de threads actifs dans le groupe de l'appelant.
- la méthode de classe enumerate(Thread[] tableau) stocke dans le tableau donné
les références des threads actifs dans le groupe
de l'appelant et ses sous-groupes. Elle renvoie le nombre de
threads actifs obtenus.
- remarquons que le thread main, renommé
bavard, a fini avant le thread perroquet, et ne l'attend pas
pour terminer.
|
Synchronisation
sur terminaison
Source de BavarderEtLancerLePerroquet6.java
class BavarderEtLancerLePerroquet6
{
public static void main(String args[]) {
Perroquet6 perroquet = new Perroquet6("coco",10);
perroquet.start();
for (int n=0; n<5; n++)
blabla();
try {
perroquet.join();
}
catch(InterruptedException e) {
System.out.println(e.getMessage());
System.exit(2);
}
System.out.println("fin du thread perroquet !");
for (int n=0; n<5; n++)
blabla();
}
private static void blabla() {
System.out.println("blabla");
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
}
}
class Perroquet6 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet6(String s, int i) {
super("perroquet");
cri = s;
fois = i;
}
public void repeter() {
System.out.println(cri);
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) { }
}
public void run() {
for (int n=0; n<fois; n++)
repeter();
}
}
|
EXECUTION
blabla
coco
coco
blabla
blabla
blabla
coco
coco
blabla
coco
coco
coco
coco
coco
coco
fin du thread perroquet !
blabla
blabla
blabla
blabla
blabla
|
|
- les lignes de la classe :
- la méthode join() attend la
terminaison du thread spécifié.
si
le thread est créé mais pas "starté",
il est considéré comme terminé !
- join peut aussi avoir un paramètre
donné qui est un timeout maximal.
- Les 2 threads ne sont plus indépendants
puisque le "main" attend, à une certaine étape,
la terminaison (fin d'exécution) de l'autre. C'est une
forme de synchronisation.
|
Priorités
Le bavardeur et
le Perroquet sans sleep
Source de BavarderEtLancerLePerroquet7.java
class BavarderEtLancerLePerroquet7
{
public static void main(String args[]) {
Perroquet7 perroquet = new Perroquet7("coco",10);
perroquet.start();
for (int n=0; n<10; n++)
blabla();
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet7 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet7(String s, int i) {
cri = s;
fois = i;
}
public void repeter() {
System.out.println(cri);
}
public void run() {
for (int n=0; n<fois; n++)
repeter();
}
}
|
EXECUTION
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
|
|
- le temps d'exécution est trop court
pour visualiser la répartition du CPU entre les 2 threads.
|
Source de CourseInfernale1.java
public class CourseInfernale {
public static void main(String[] args) {
Coureur hinaut = new Coureur("Hinaut");
Coureur poulidor = new Coureur("Poulidor");
hinaut.start();
poulidor.start();
}
}
class Coureur extends Thread {
String nom;
public Coureur(String nom) {
super(nom);
this.nom = nom;
}
public void run() {
long nombreFoulee = 0;
while (nombreFoulee < 5000000L) {
nombreFoulee++;
if ((nombreFoulee % 500000L) == 0) {
System.out.println("Coureur " + nom
+ " a couru " + nombreFoulee + " foulees");
}
}
}
}
|
EXECUTION
Coureur Hinaut a donne 500000 coups de pedale.
Coureur Poulidor a donne 500000 coups de pedale.
Coureur Hinaut a donne 1000000 coups de pedale.
Coureur Poulidor a donne 1000000 coups de pedale.
Coureur Hinaut a donne 1500000 coups de pedale.
Coureur Poulidor a donne 1500000 coups de pedale.
Coureur Hinaut a donne 2000000 coups de pedale.
Coureur Poulidor a donne 2000000 coups de pedale.
Coureur Poulidor a donne 2500000 coups de pedale.
Coureur Hinaut a donne 2500000 coups de pedale.
Coureur Hinaut a donne 3000000 coups de pedale.
Coureur Poulidor a donne 3000000 coups de pedale.
Coureur Hinaut a donne 3500000 coups de pedale.
Coureur Poulidor a donne 3500000 coups de pedale.
Coureur Hinaut a donne 4000000 coups de pedale.
Coureur Poulidor a donne 4000000 coups de pedale.
Coureur Hinaut a donne 4500000 coups de pedale.
Coureur Poulidor a donne 4500000 coups de pedale.
Coureur Hinaut a donne 5000000 coups de pedale.
Coureur Poulidor a donne 5000000 coups de pedale.
|
|
Java
n'impose pas que le système soit "time-sliced"
: cad que la même quantité de temps soit impartie
aux threads de même niveau de priorité
|
Source de CourseInfernale2.java
public class CourseInfernale2 {
public static void main(String[] args) {
Coureur hinaut = new Coureur("Hinaut");
Coureur poulidor = new Coureur("Poulidor");
hinaut.setPriority(Thread.MAX_PRIORITY);
poulidor.setPriority(Thread.MIN_PRIORITY);
System.out.println("Thread Coureur " + hinaut.nom
+ " a la priorite = " + hinaut.getPriority());
System.out.println("Thread Coureur " + poulidor.nom
+ " a la priorite = " + poulidor.getPriority());
hinaut.start();
poulidor.start();
}
}
class Coureur extends Thread {
String nom;
public Coureur(String nom) {
super(nom);
this.nom = nom;
}
public void run() {
long coupsDePedale = 0;
while (coupsDePedale < 5000000L) {
coupsDePedale++;
if ((coupsDePedale % 500000L) == 0) {
System.out.println("Coureur " + nom
+ " a donne " + coupsDePedale + " coups de pedale.");
}
}
}
}
|
EXECUTION
Thread Coureur Hinaut a la priorite = 10
Thread Coureur Poulidor a la priorite = 1
Coureur Hinaut a donne 500000 coups de pedale.
Coureur Hinaut a donne 1000000 coups de pedale.
Coureur Hinaut a donne 1500000 coups de pedale.
Coureur Hinaut a donne 2000000 coups de pedale.
Coureur Hinaut a donne 2500000 coups de pedale.
Coureur Hinaut a donne 3000000 coups de pedale.
Coureur Hinaut a donne 3500000 coups de pedale.
Coureur Hinaut a donne 4000000 coups de pedale.
Coureur Hinaut a donne 4500000 coups de pedale.
Coureur Hinaut a donne 5000000 coups de pedale.
Coureur Poulidor a donne 500000 coups de pedale.
Coureur Poulidor a donne 1000000 coups de pedale.
Coureur Poulidor a donne 1500000 coups de pedale.
Coureur Poulidor a donne 2000000 coups de pedale.
Coureur Poulidor a donne 2500000 coups de pedale.
Coureur Poulidor a donne 3000000 coups de pedale.
Coureur Poulidor a donne 3500000 coups de pedale.
Coureur Poulidor a donne 4000000 coups de pedale.
Coureur Poulidor a donne 4500000 coups de pedale.
Coureur Poulidor a donne 5000000 coups de pedale.
|
|
- les lignes de la classe :
- la méthode setPriority fixe le
niveau de priorité entre les différents threads
- la valeur doit être comprise entre
une valeur minimale, variable de classe MIN_PRIORITY, et maximale,
MAX_PRIORITY
- le temps alouée fut visiblement
plus court que dans la version 1 de la course infernale !
|
yield
...
Source de BavarderEtLancerLePerroquet8.java
class BavarderEtLancerLePerroquet8
{
public static void main(String args[]) {
Perroquet8 perroquet = new Perroquet8("coco",10);
perroquet.start();
for (int n=0; n<10; n++) {
blabla();
Thread.currentThread().yield();
}
}
private static void blabla() {
System.out.println("blabla");
}
}
class Perroquet8 extends Thread
{
private String cri = null;
private int fois = 0;
public Perroquet8(String s, int i) {
cri = s;
fois = i;
}
public void repeter() {
System.out.println(cri);
}
public void run() {
for (int n=0; n<fois; n++) {
repeter();
yield();
}
}
}
|
EXECUTION
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
blabla
coco
|
|
- les lignes de la classe :
- la méthode yield() "rend
le processeur" : elle indique au contrôlleur d'exécution
des threads d'en choisir un nouveau à exécuter
(donc ca pourrait être le même !)
elle
est interressante dans peu de cas
|
Essayer
de Stopper l'exécution d'un thread
Source de LancerEtArreterLePerroquet9.java
class LancerEtArreterLePerroquet9
{
public static void main(String args[]) {
Perroquet9 perroquet = new Perroquet9("coco");
perroquet.start();
String reponse="oui";
do {
System.out.println("voulez-vous que le perroquet continue ? (o/n)");
Thread.currentThread().yield();
reponse = Clavier.lireString();
}
while (reponse.equals("o"));
}
}
class Perroquet9 extends Thread
{
private String cri = null;
public Perroquet9(String s) {
cri = s;
}
public void repeter() {
System.out.println(cri);
try {
Thread.sleep((int)Math.random()*1000);
}
catch(InterruptedException e) {}
}
public void run() {
while (true) {
repeter();
yield();
}
}
}
|
EXECUTION
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
...
|
|
- Le probléme est que l'arret de
l'exécution du thread main n'entraine pas l'arret du thread
perroquet
- la Classe Thread a une méthode
stop() "deprecated" : l'arret était brutal et
pouvait laisser des objets dans des états inconsistants
! par exemple, des verrous pouvaient avoir été
posés. C'est au programmeur de prévoir quand (et
donc comment) l'exécution du thread peut s'arreter sans
risque.
- idem pour suspend( ) et resume( ) qui
suspendait et reprenait l'exécution d'un thread
|
Interrompre
un thread
Source de LancerEtArreterLePerroquet13.java
class LancerEtArreterLePerroquet13
{
public static void main(String args[]) {
Perroquet13 perroquet = new Perroquet13("coco");
perroquet.start();
String reponse="n";
do {
System.out.println("voulez-vous interrompre le perroquet ?(o/n)");
Thread.currentThread().yield();
reponse = Clavier.lireString();
}
while (! reponse.equals("o"));
perroquet.interrupt();
}
}
class Perroquet13 extends Thread
{
private String cri = null;
public Perroquet13(String s) {
cri = s;
}
public void repeter() throws InterruptedException {
System.out.println(cri);
Thread.sleep((int)(Math.random()*3000));
}
public void run() {
try {
while (true) {
repeter();
yield();
}
}
catch(InterruptedException e) {
System.out.println("perroquet interrompu :\n"
+ e.getMessage());
}
}
}
|
EXECUTION
voulez-vous interrompre le perroquet ?(o/n)
coco
coco
coco
coco
n
voulez-vous interrompre le perroquet ?(o/n)
coco
coco
o
perroquet interrompu :
sleep interrupted
|
|
- les lignes de la classe :
- il est possible d'interrompre un thread
- le thread interrompu termine immédiatement
son exécution de la méthode run()
- une exception est levée puis capturée
- la méthode interrupt() de Thread
interrompt le thread et lève une exception InterruptedException
- la méthode sleep() est susceptible
de générer une exception InterruptedException puisque
que c'est la seule façon de "sortir avant terme".
c'est
une technique violente pour terminer un thread : il faut au moins
faire un try-catch de l'exception InterruptedException sur tout
le bloc de run() pour essayer de terminer proprement (annuler
les locks, ...)
|
Stopper
proprement
Source de LancerEtArreterLePerroquet10.java
class LancerEtArreterLePerroquet10
{
public static void main(String args[]) {
Perroquet10 perroquet = new Perroquet10("coco");
perroquet.start();
String reponse="o";
do {
System.out.println("voulez-vous que le perroquet continue ? (o/n)");
Thread.currentThread().yield();
reponse = Clavier.lireString();
}
while (reponse.equals("o"));
perroquet.stopper();
}
}
class Perroquet10 extends Thread
{
private volatile boolean continuer = true;
private String cri = null;
public Perroquet10(String s) {
continuer = true;
cri = s;
}
public void repeter() {
System.out.println(cri);
try {
Thread.sleep((int)Math.random()*2000);
}
catch(InterruptedException e) { }
}
public void stopper() {
continuer = false;
}
public void run() {
while (continuer) {
repeter();
yield();
}
}
}
|
EXECUTION
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
coco
ncoco
coco
coco
coco
coco
coco
|
|
- les lignes de la classe :
- La solution est très simple : un
drapeau booléen sert dans la méthode run pour savoir
s'il faut continuer ou arreter.
- cette variable doit être déclarée
volatile
afin
d'empêcher toute optimisation du code qui entrainerait
la création de double temporaire de cette variable
|
Timer
Source de DeclancherLePerroquet11.java
import java.util.TimerTask;
import java.util.Timer;
class DeclancherLePerroquet11
{
public static void main(String args[]) {
Perroquet11 perroquet = new Perroquet11("coco", 3);
Timer timer = new Timer();
timer.schedule(perroquet, 4000);
String reponse="oui";
do {
System.out.println("blabla");
System.out.println("blabla");
System.out.println("voulez-vous encore bavarder ? (o/n)");
reponse = Clavier.lireString();
}
while (reponse.equals("o"));
timer.cancel();
}
}
class Perroquet11 extends TimerTask
{
private String cri = null;
private int fois = 0;
public Perroquet11(String s, int i) {
cri = s;
fois = i;
}
public void repeter() {
System.out.println(cri);
}
public void run() {
for (int i = 0; i < fois; i++) {
repeter();
}
}
}
|
EXECUTION
blabla
blabla
voulez-vous encore bavarder ? (o/n)
o
blabla
blabla
voulez-vous encore bavarder ? (o/n)
coco
coco
coco
o
blabla
blabla
voulez-vous encore bavarder ? (o/n)
n
|
|
- les lignes de la classe :
- Un Timer permet de déclancher
l'exécution de taches une ou plusieurs fois en précisant
un délai initial et/ou une périodicité.
- plusieurs taches peuvent etre programmées
selon des programmes divers.
- A un Timer correspond un thread qui exécutera
successivement les taches à effectuer.
- Les taches sont des TimerTask et doivent
être courte
- Aucune garantie de temps réel n'est
assurée par ce mécanisme
- la méthode schedule(...) permet
de programmer les tachesla méthode
- schedule(tache, long millisecondes) programme la tache toutes les millisecondes
- la méthode cancel() arrete toute
la programmation du Timer, mais si une tache est en cours, elle
continue son execution
- la classe abstraite TimerTask implémente
Runnable, donc une méthode run()
- il faut donc hériter de la classe
TimerTask et redéfinir la méthode run() qui code
la tache à effectuer.
|
Source de DeclancherLePerroquet12.java
...
timer.schedule(perroquet, 2000, 1000);
...
|
- les lignes de la classe :
- schedule(tache, long delai, long période) programme la tache après un délai
pour une exécution périodiques : les temps sont
donnés en millisecondes
Exercices
Source de Ecrivain1.java
import java.util.Vector;
import java.util.StringTokenizer;
public class Ecrivain1 extends Thread {
private Vector texte;
public Ecrivain1(String t) {
super();
texte = new Vector();
StringTokenizer st = new StringTokenizer(t);
while (st.hasMoreTokens())
texte.addElement(st.nextToken());
}
public void run() {
for (int i=0; i<10; i++) {
int j=0;
for (;j<texte.size()-1; j++) {
System.out.print(texte.elementAt(j)+" ");
try {
sleep((long)(Math.random() * 100));
} catch (InterruptedException e) {}
}
System.out.println(texte.elementAt(j));
}
System.out.println("ecrivain de "+texte+" a fini");
}
}
|
- les lignes de la classe :
- un écrivain écrit :
- 10 fois une phrase
- mollement ! cad en écrivant lettre
par lettre et en faisant la pause entre chaque lettre
- 2 écrivains indépendants
Ecrire un
programme correction qui crée 2 écrivains
:
- l'un écrit
la phrase "Etre ou ne pas etre.",
- l'autre écrit
la phrase "To be or not to be."
- indépendemment l'un de l'autre
Etre To ou be ne or pas not to etre.
Etre ou ne be.
To pas be or not etre.
Etre to ou be.
To be or not ne to pas be.
To be etre.
Etre or not ou to be.
To ne pas be or etre.
Etre ou ne not pas etre.
Etre to be.
To ou ne be pas or not etre.
Etre to ou be.
To ne be pas or not to etre.
Etre be.
To be or ou ne not pas to etre.
Etre be.
To ou be ne or pas not etre.
Etre to ou ne be.
To be or pas etre.
ecrivain de [Etre, ou, ne, pas, etre.] a fini
not to be.
ecrivain de [To, be, or, not, to, be.] a fini
|
- Terminaison :
Le programme "main" attendra que les 2 écrivains
aient finis leurs écritures pour afficher un "bonsoir"
et arreter.
correction
- Accélerer
"Doublez" (si possible)
la vitesse d'écriture d'un des 2 écrivains par
rapport à l'autre
correction
- Stopper
Donnez la possibilité au thread main d'arrêter un
ou les 2 écrivains
correction correction
- Programmation temporelle
Un seul écrivain écrira son texte plusieurs fois
ainsi : il l'écrira 10 fois à 2 secondes d'intervalles;
4 secondes s'écouleront avant la 1ère écriture;
il "prend" environ 50 millisecondes pour écrire
chaque lettre.
correction