 |
 |
 |
14) Les Threads multiples |
|
 |
|
Texte original |
 |
Traducteur : Cédric BABAULT |
|
 |
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
The output that follows has been edited
to allow it to fit on the page (the java.lang. has been removed) and to
add numbers to correspond to the commented numbers in the listing
above.
|
 |
La sortie qui suit a été édité pour lui
permettre de tenir sur la page (le java.lang. a été supprimé) et pour
ajouter des numéros correspondant à ceux des commentaires du listing
précédent.
|
 |
 |
 |
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system] (2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system] (3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1] (4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] (5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1] (6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1] (7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] (8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3] (10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2] Starting all threads: All threads started
|
 |
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system] (2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system] (3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1] (4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] (5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1] (6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1] (7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] (8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3] (10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2] Starting all threads: All threads started
|
 |
 |
 |
All programs have at least one thread
running, and the first action in main( ) is to call the
static method of Thread called currentThread( ). From
this thread, the thread group is produced and list( ) is called for
the result. The output is:
|
 |
Tous les programmes ont au moins un thread qui tourne, et la
première action de main() est d'appeler la méthode static de
Thread nommée currentThread(). Depuis ce thread, le groupe de thread est
produit et list() est appelé sur le résultat. La sortie est:
|
 |
 |
 |
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system]
|
 |
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system]
|
 |
 |
 |
You can see that the name of the main
thread group is system, and the name of the main thread is main,
and it belongs to the system thread group.
|
 |
Vous pouvez voir que le nom du groupe de thread principal est
system, et le nom du thread principal est main, et il appartient au groupe de thread
system.
|
 |
 |
 |
The second exercise shows that the
system group’s maximum priority can be reduced and the main
thread can have its priority increased:
|
 |
Le second exercice montre que la priorité maximum du groupe
system peut être réduite et le thread main peut avoir sa priorité
augmentée.
|
 |
 |
 |
(2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system]
|
 |
(2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system]
|
 |
 |
 |
The third exercise creates a new thread
group, g1, which automatically belongs to the system thread group
since it isn’t otherwise specified. A new thread A is placed in
g1. After attempting to set this group’s maximum priority to the
highest level and A’s priority to the highest level, the result
is:
|
 |
Le troisième exercice crée un nouveau groupe de thread,
g1, qui appartient automatiquement au groupe de thread system puisqu'il n'est rien
spécifié d'autre. Un nouveau thread A est placé dans g1.
Après avoir essayer de positionner la priorité maximum de ce groupe au plus haut
niveau possible et la priorité de A au niveau le plus élevé, le
résultat est:
|
 |
 |
 |
(3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1]
|
 |
(3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1]
|
 |
 |
 |
Thus, it’s not possible to change
the thread group’s maximum priority to be higher than its parent thread
group.
|
 |
Ainsi, il n'est pas possible de changer la priorité maximum d'un
groupe de thread au delà de celle de son groupe de thread parent.
|
 |
 |
 |
The fourth exercise reduces
g1’s maximum priority by two and then tries to increase it up to
Thread.MAX_PRIORITY. The result is:
|
 |
Le quatrième exercice réduit la priorité maximum de
g1 de deux et essaie ensuite de l'augmenter jusqu'à Thread.MAX_PRIORITY. Le
résultat est:
|
 |
 |
 |
(4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1]
|
 |
(4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1]
|
 |
 |
 |
You can see that the increase in maximum
priority didn’t work. You can only decrease a thread group’s maximum
priority, not increase it. Also, notice that thread A’s priority
didn’t change, and now it is higher than the thread group’s maximum
priority. Changing a thread group’s maximum priority doesn’t affect
existing threads.
|
 |
Vous pouvez voir que l'augmentation à la priorité maximum ne
fonctionne pas. Vous pouvez seulement diminuer la priorité maximum d'un groupe de thread,
pas l'augmenter. Notez également que la priorité du thread A n'a pas
changé, et est maintenant plus grande que la priorité maximum du groupe de thread.
Changer la priorité maximum d'un groupe de thread n'affecte pas les threads
existantes.
|
 |
 |
 |
The fifth exercise attempts to set a new
thread to maximum priority:
|
 |
Le cinquième exercice essaie de créer un nouveau thread avec
une priorité au maximum:
|
 |
 |
 |
(5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1]
|
 |
(5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1]
|
 |
 |
 |
The new thread cannot be changed to
anything higher than the maximum thread group priority.
|
 |
Le nouveau thread ne peut pas être changer à une
priorité plus haute que la priorité maximum du groupe de thread.
|
 |
 |
 |
The default thread priority for this
program is six; that’s the priority a new thread will be created at and
where it will stay if you don’t manipulate the priority. Exercise 6 lowers
the maximum thread group priority below the default thread priority to see what
happens when you create a new thread under this condition:
|
 |
La priorité par défaut du thread pour ce programme est six;
c'est la priorité avec laquelle un nouveau thread sera créé et à
laquelle il restera si vous ne manipulez pas la priorité. L'exercice 6 diminue la
priorité maximum du groupe de thread en dessous de la priorité par défaut pour
voir ce qui se passe quand vous créez un nouveau thread dans ces conditions:
|
 |
 |
 |
(6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1]
|
 |
(6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1]
|
 |
 |
 |
Even though the maximum priority of the
thread group is three, the new thread is still created using the default
priority of six. Thus, maximum thread group priority does not affect default
priority. (In fact, there appears to be no way to set the default priority for
new threads.)
|
 |
Étant donné que la priorité maximum du groupe de
thread est trois, le nouveau thread est encore créer en utilisant la priorité par
défaut de six. Ainsi, la priorité maximum du groupe de thread n'affecte pas la
priorité par défaut. (En fait, il ne semble pas y avoir de moyen pour positionner la
priorité par défaut des nouveaux threads.)
|
 |
 |
 |
After changing the priority, attempting
to decrement it by one, the result is:
|
 |
Après avoir changer la priorité, en essayant de la
décrémenter par pas de un, le résultat est:
|
 |
 |
 |
(7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1]
|
 |
(7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1]
|
 |
 |
 |
Only when you attempt to change the
priority is the thread group’s maximum priority enforced.
|
 |
La priorité maximum du groupe de thread est forcé seulement
lorsque vous essayez de changer la priorité du thread.
|
 |
 |
 |
A similar experiment is performed in (8)
and (9), in which a new thread group g2 is created as a child of
g1 and its maximum priority is changed. You can see that it’s
impossible for g2’s maximum to go higher than
g1’s:
|
 |
Une expérience similaire est effectué en (8) et (9), dans
lequel un nouveau groupe de thread g2 est créé comme un fils de g1 et
sa priorité maximum est changée. Vous pouvez voir qu'il n'est pas impossible pour la
priorité maximum de g2 de devenir plus grande que celle de g1:
|
 |
 |
 |
(8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3]
|
 |
(8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3]
|
 |
 |
 |
Also notice that g2 is
automatically set to the thread group maximum priority of g1 as g2
is created.
|
 |
Notez également que g2 est automatiquement mise à la
priorité maximum du groupe de thread g1 dès la création de
g2.
|
 |
 |
 |
After all of these experiments, the
entire system of thread groups and threads is printed:
|
 |
Après toutes ces expériences, le système de groupes de
threads est entièrement donné:
|
 |
 |
 |
(10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2]
|
 |
(10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2]
|
 |
 |
 |
So because of the rules of thread groups,
a child group must always have a maximum priority that’s less than or
equal to its parent’s maximum priority.
|
 |
Donc à cause des règles sur les groupes de threads, un groupe
fils doit toujours avoir une priorité maximum plus petite ou égale à celle de
son parent.
|
 |
 |
 |
The last part of this program
demonstrates methods for an entire group of threads. First the program moves
through the entire tree of threads and starts each one that hasn’t been
started. For drama, the system group is then suspended and finally
stopped. (Although it’s interesting to see that suspend( ) and
stop( ) work on entire thread groups, you should keep in mind that
these methods are deprecated in Java 2.) But when you suspend the system
group you also suspend the main thread and the whole program shuts down,
so it never gets to the point where the threads are stopped. Actually, if you do
stop the main thread it throws a ThreadDeath exception, so this is
not a typical thing to do. Since ThreadGroup is inherited from
Object, which contains the wait( ) method, you can also
choose to suspend the program for any number of seconds by calling
wait(seconds * 1000). This must acquire the lock inside a synchronized
block, of course.
|
 |
La dernière partie de ce programme démontre les
méthodes pour un groupe de threads entier. Dans un premier temps le programme parcourt
l'intégralité de l'arbre de threads et démarre chaque thread qui ne l'est pas
déjà. Par drame, le groupe system est alors suspendu et finalement
arrêter. (Bien qu'il soit intéressant de voir que suspend() et stop()
fonctionnent sur un groupe de thread entier, vous devez garder en tête que ces
méthodes sont dépréciées en Java 2.) Mais quand vous suspendez le
groupe system vous suspendez aussi le thread main et le programme entier
s'arrête, donc il ne quittera jamais le point où les threads sont stoppés.
Actuellement, si vous stoppez le thread main il déclenche un exception
ThreadDeath, ce n'est donc pas une chose à faire. Puisque ThreadGroup
hérite de Object, qui contient la méthode wait(), vous pouvez aussi
choisir de suspendre le programme pour un certain nombre de secondes en appelant wait(secondes *
1000). Ce qui doit acquérir le verrou dans un bloc synchronised, bien
sûr.
|
 |
 |
 |
The ThreadGroup class also has
suspend( ) and resume( ) methods so you can stop and
start an entire thread group and all of its threads and subgroups with a single
command. (Again, suspend( ) and resume( ) are deprecated
in Java 2.)
|
 |
La classe ThreadGroup a aussi des méthodes suspend()
et resume() donc vous pouvez arrêter et démarrer un groupe de thread entier et
toutes ces threads et sous-groupes avec une seule commande. (Encore un fois, suspend() et
resume() sont déprécié en Java 2.)
|
 |
 |
 |
Thread groups can seem a bit mysterious
at first, but keep in mind that you probably won’t be using them directly
very
often.
|
 |
Les groupes de threads peuvent paraître un peu mystérieux au
premier abord, mais garder en mémoire que vous ne les utiliserez probablement directement
très peu souvent.
|
 |
 |
 |
Runnable revisited
|
 |
Runnable revisité
|
 |
 |
 |
Earlier in this chapter, I suggested that
you think carefully before making an applet or main Frame as an
implementation of
Runnable.
Of course, if you must inherit from a class and you want to add threading
behavior to the class, Runnable is the correct solution. The final
example in this chapter exploits this by making a Runnable JPanel
class that paints different colors on itself. This application is set up to take
values from the command line to determine how big the grid of colors is and how
long to sleep( ) between color changes. By playing with these values
you’ll discover some interesting and possibly inexplicable features of
threads:
|
 |
Précédemment dans ce chapitre, j'ai suggéré que
vous deviez faire très attention avant de faire d'une applet ou une Frame principale
une implémentation de Runnable. Bien sûr, si vous devez héritez d'une
classe et que vous voulez ajouter un comportement multitâche à la classe,
Runnable est la solution correcte. L'exemple final de ce chapitre exploite ceci en
créant une classe Runnable JPanel qui se peint de différentes couleurs.
Cette application est prend des valeurs depuis la ligne de commande pour déterminer la
taille de la grille de couleurs et la durée du sleep() entre les changements de
couleurs. En jouant sur ces valeurs vous découvrirez des possibilités
intéressantes et parfois inexplicable des threads:
|
 |
 |
 |
//: c14:ColorBoxes.java // Using the Runnable interface. // <applet code=ColorBoxes width=500 height=400> // <param name=grid value="12"> // <param name=pause value="50"> // </applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*;
class CBox extends JPanel implements Runnable { private Thread t; private int pause; private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } public CBox(int pause) { this.pause = pause; t = new Thread(this); t.start(); } public void run() { while(true) { cColor = newColor(); repaint(); try { t.sleep(pause); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } }
public class ColorBoxes extends JApplet { private boolean isApplet = true; private int grid = 12; private int pause = 50; public void init() { // Get parameters from Web page: if (isApplet) { String gsize = getParameter("grid"); if(gsize != null) grid = Integer.parseInt(gsize); String pse = getParameter("pause"); if(pse != null) pause = Integer.parseInt(pse); } Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); for (int i = 0; i < grid * grid; i++) cp.add(new CBox(pause)); } public static void main(String[] args) { ColorBoxes applet = new ColorBoxes(); applet.isApplet = false; if(args.length > 0) applet.grid = Integer.parseInt(args[0]); if(args.length > 1) applet.pause = Integer.parseInt(args[1]); Console.run(applet, 500, 400); } } ///:~
|
 |
//: c14:ColorBoxes.java // Utilisation de l'interface Runnable. // <applet code=ColorBoxes width=500 height=400> // <param name=grid value="12"> // <param name=pause value="50"> // </applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*;
class CBox extends JPanel implements Runnable { private Thread t; private int pause; private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } public CBox(int pause) { this.pause = pause; t = new Thread(this); t.start(); } public void run() { while(true) { cColor = newColor(); repaint(); try { t.sleep(pause); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } }
public class ColorBoxes extends JApplet { private boolean isApplet = true; private int grid = 12; private int pause = 50; public void init() { // Récupère les paramètres depuis la page web: if (isApplet) { String gsize = getParameter("grid"); if(gsize != null) grid = Integer.parseInt(gsize); String pse = getParameter("pause"); if(pse != null) pause = Integer.parseInt(pse); } Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); for (int i = 0; i < grid * grid; i++) cp.add(new CBox(pause)); } public static void main(String[] args) { ColorBoxes applet = new ColorBoxes(); applet.isApplet = false; if(args.length > 0) applet.grid = Integer.parseInt(args[0]); if(args.length > 1) applet.pause = Integer.parseInt(args[1]); Console.run(applet, 500, 400); } } ///:~
|
 |
 |
 |
ColorBoxes is the usual
applet/application with an init( ) that sets up the GUI. This sets
up the GridLayout so that it has grid
cells in each dimension. Then it adds the appropriate number of CBox
objects to fill the grid, passing the pause value to each one. In
main( ) you can see how pause and grid have default
values that can be changed if you pass in command-line arguments, or by using
applet parameters.
|
 |
ColorBoxes est l'applet/application habituelle avec une
méthode init() qui créé la GUI. Elle positionne la GridLayout
afin d'avoir une grille de cellules dans chaque dimension. Ensuite elle ajoute le nombre
approprié d'objet CBox pour remplir la grille, passant la valeur pause a
chacune. Dans main() vous pouvez voir comment pause et grid ont des valeurs
par défaut qui peuvent être changées si vous passez des arguments à la
ligne de commande, ou en utilisant des arguments de l'applet.
|
 |
 |
 |
CBox is where all the work takes
place. This is inherited from JPanel and it
implements the Runnable interface so each JPanel can also be a
Thread. Remember that when you implement Runnable, you don’t
make a Thread object, just a class that has a run( ) method.
Thus, you must explicitly create a Thread object and hand the
Runnable object to the constructor, then call start( ) (this
happens in the constructor). In CBox this thread is called
t.
|
 |
CBox est là où tout le travail s'effectue. Elle
hérite de JPanel et implémente l'interface Runnable ainsi chaque
JPanel peut aussi être un Thread. Souvenez vous que quand vous
implémentez Runnable, vous ne faites pas un objet Thread, mais juste une
classe qui a une méthode run(). Ainsi, vous devez créer explicitement un objet
Thread et passer l'objet Runnable au constructeur, puis appelez start() (ce
qui est fait dans le constructeur). Dans CBox ce thread est appelé
t.
|
 |
 |
 |
Notice the array colors, which is
an enumeration of all the colors in class Color. This is used in
newColor( ) to produce a randomly selected color. The current cell
color is cColor.
|
 |
Remarquez le tableau colors, qui est une énumération
de toutes les couleurs de la classe Color. Il est utilisé dans newColor() pour
produire une couleur sélectionnée au hasard. La couleur de la cellule courante est
cColor.
|
 |
 |
 |
paintComponent( ) is quite
simple—it just sets the color to cColor and fills the entire
JPanel with that color.
|
 |
paintComponent() est assez simple — elle place juste
la couleur à cColor et remplit intégralement le JPanel avec cette
couleur.
|
 |
 |
 |
In run( ), you see the
infinite loop that sets the cColor to a new random color and then calls
repaint( ) to show it. Then the thread goes to sleep( )
for the amount of time specified on the command line.
|
 |
Dans run(), vous voyez la boucle infinie qui place la cColor
à une nouvelle couleur prise au hasard et ensuite appelle repaint() pour la montrer.
Puis le thread passe dans sleep() pour le temps spécifié sur la ligne de
commande.
|
 |
 |
 |
Precisely because this design is flexible
and threading is tied to each JPanel element, you can experiment by
making as many threads as you want. (In reality, there is a restriction imposed
by the number of threads your JVM can comfortably handle.)
|
 |
C'est précisément parce que le design est flexible et que le
threading est attaché à chaque élément JPanel, que vous pouvez
expérimenter en créant autant de threads que vous voulez. (En réalité,
il y a une restriction imposé par le nombre de threads que votre JVM peut confortablement
gérés.)
|
 |
 |
 |
This program also makes an interesting
benchmark, since it can show dramatic performance differences between one JVM
threading implementation and
another.
|
 |
Ce programme fait aussi un benchmark intéressant, puisqu'il peut
montrer des différences de performance dramatiques entre deux implémentation du
threading dans les JVM.
|
 |
 |
 |
Too many threads
|
 |
Trop de threads
|
 |
 |
 |
At some point, you’ll find that
ColorBoxes bogs down. On my machine, this occurred somewhere after a 10 x
10 grid. Why does this happen? You’re naturally suspicious that Swing
might have something to do with it, so here’s an example that tests that
premise by making fewer threads. The following code is reorganized so that an
ArrayList implements Runnable and that ArrayList holds a
number of color blocks and randomly chooses ones to update. Then a number of
these ArrayList objects are created, depending roughly on the grid
dimension you choose. As a result, you have far fewer threads than color blocks,
so if there’s a speedup we’ll know it was because there were too
many threads in the previous example:
|
 |
A un certain point, vous trouverez que ColorBoxes ralentit. Sur ma
machine, cela se passe quelque part après une grille 10 x 10. Pourquoi est ce que cela
arrive? Vous soupçonner naturellement que Swing ai quelques chose à voir avec
ça, donc voici un exemple qui test ce prémisse en faisant moins de threads. Le code
suivant est réorganisé afin qu'une ArrayList implements Runnable et
cette ArrayList gère un nombre de blocs de couleurs et en choisit une au hasard pour
la mise à jour. Puis un certain nombre de ces objets ArrayList sont
créés, en fonction d'une approximation de la dimension de la grille que vous
choisissez. Au résultat, vous avez beaucoup moins de threads que de blocs de couleurs, donc
si il y a une accélération nous saurons que c'était à cause du trop
grand nombre de threads dans l'exemple précédent:
|
 |
 |
 |
//: c14:ColorBoxes2.java // Balancing thread use. // <applet code=ColorBoxes2 width=600 height=500> // <param name=grid value="12"> // <param name=pause value="50"> // </applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import com.bruceeckel.swing.*;
class CBox2 extends JPanel { private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } void nextColor() { cColor = newColor(); repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } }
class CBoxList extends ArrayList implements Runnable { private Thread t; private int pause; public CBoxList(int pause) { this.pause = pause; t = new Thread(this); } public void go() { t.start(); } public void run() { while(true) { int i = (int)(Math.random() * size()); ((CBox2)get(i)).nextColor(); try { t.sleep(pause); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } public Object last() { return get(size() - 1);} }
public class ColorBoxes2 extends JApplet { private boolean isApplet = true; private int grid = 12; // Shorter default pause than ColorBoxes: private int pause = 50; private CBoxList[] v; public void init() { // Get parameters from Web page: if (isApplet) { String gsize = getParameter("grid"); if(gsize != null) grid = Integer.parseInt(gsize); String pse = getParameter("pause"); if(pse != null) pause = Integer.parseInt(pse); } Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); v = new CBoxList[grid]; for(int i = 0; i < grid; i++) v[i] = new CBoxList(pause); for (int i = 0; i < grid * grid; i++) { v[i % grid].add(new CBox2()); cp.add((CBox2)v[i % grid].last()); } for(int i = 0; i < grid; i++) v[i].go(); } public static void main(String[] args) { ColorBoxes2 applet = new ColorBoxes2(); applet.isApplet = false; if(args.length > 0) applet.grid = Integer.parseInt(args[0]); if(args.length > 1) applet.pause = Integer.parseInt(args[1]); Console.run(applet, 500, 400); } } ///:~
|
 |
//: c14:ColorBoxes2.java // Compromis dans l'utilisation de thread. // <applet code=ColorBoxes2 width=600 height=500> // <param name=grid value="12"> // <param name=pause value="50"> // </applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import com.bruceeckel.swing.*;
class CBox2 extends JPanel { private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } void nextColor() { cColor = newColor(); repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } }
class CBoxList extends ArrayList implements Runnable { private Thread t; private int pause; public CBoxList(int pause) { this.pause = pause; t = new Thread(this); } public void go() { t.start(); } public void run() { while(true) { int i = (int)(Math.random() * size()); ((CBox2)get(i)).nextColor(); try { t.sleep(pause); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } public Object last() { return get(size() - 1);} }
public class ColorBoxes2 extends JApplet { private boolean isApplet = true; private int grid = 12; // Pause par défaut plus courte que dans ColorBoxes: private int pause = 50; private CBoxList[] v; public void init() { // Récupère les paramètres de la page Web: if (isApplet) { String gsize = getParameter("grid"); if(gsize != null) grid = Integer.parseInt(gsize); String pse = getParameter("pause"); if(pse != null) pause = Integer.parseInt(pse); } Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); v = new CBoxList[grid]; for(int i = 0; i < grid; i++) v[i] = new CBoxList(pause); for (int i = 0; i < grid * grid; i++) { v[i % grid].add(new CBox2()); cp.add((CBox2)v[i % grid].last()); } for(int i = 0; i < grid; i++) v[i].go(); } public static void main(String[] args) { ColorBoxes2 applet = new ColorBoxes2(); applet.isApplet = false; if(args.length > 0) applet.grid = Integer.parseInt(args[0]); if(args.length > 1) applet.pause = Integer.parseInt(args[1]); Console.run(applet, 500, 400); } } ///:~
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |
|
 |