Programmation concurrente de 2 threads Java :
sinus || cosinus = ?


class Ball
{
final static boolean SINE = true, COSINE = false;
double x, y, angleX = 0, angleY = 0;
int radius = 8, steps = 100, scale = 5;

public Ball(int x,int y){ this.x = x; this.y = y; }

public void paint(Graphics g,Color color){
g.setColor(color);
g.fillOval((int)x-radius,(int)y-radius,radius*2,radius*2);
g.setColor(Color.black);
g.fillOval((int)x,(int)y,2,2);
}

public void
sine(){
angleY += (2*Math.PI/steps);
y += scale*Math.sin(angleY);
}
public void
cosine(){
angleX += (2*Math.PI/steps);
x += scale*Math.sin(angleX+Math.PI/2);
}
}

Le thread de mouvement en sinus ou en cosinus :

class Move extends Thread
{
Ball ball;
Applet applet;
boolean move;

public Move(Ball b,Applet a,boolean m){ ball = b; applet = a; move = m; }
public void run(){
for(;;){
if (move == Ball.SINE) ball.sine(); else ball.cosine();
applet.paint(applet.getGraphics());
}
}
}

L'applet :

public class SinCos extends DoubleBufferedApplet
{

Ball ball = new Ball(startx,starty);

public void paint(Graphics g) { super.paint(g); ball.paint(g,Color.red); }

void circle(Ball ball){
new Move(ball,this,Ball.SINE).start();
new Move(ball,this,Ball.COSINE).start();
}

public void init(){ circle(ball); }
}

résultat


Utilisation de yield

public void run(){
for(;;){
if (move == Ball.SINE) ball.sine(); else ball.cosine();
applet.paint(applet.getGraphics());
Thread.yield();
}
}

résultat

(marche en coopératif...)


Utilisation de sleep

public void run(){
for(;;){
if (move == Ball.SINE) ball.sine(); else ball.cosine();
applet.paint(applet.getGraphics());
try{
Thread.sleep(5);}catch(Exception e){System.out.println(e);}
}
}

résultat

pas portable


La solution

public void run(){
for(;;){
synchronized(ball){
if (move == Ball.SINE) ball.sine(); else ball.cosine();
applet.paint(applet.getGraphics());
ball.notify();
try{
ball.wait();}catch(Exception e){System.out.println(e);}
}
}
}

résultat


Plusieurs balles...

void circle(Ball ball){
new Move(ball,this,Ball.SINE).start();
new Move(ball,this,Ball.COSINE).start();
}

public void init(){
circle(ball1);
circle(ball2);
circle(ball3);
}

résultat

Les balles ne tournent pas à la même vitesse...

Et que se passe-t-il lorsque il y a plusieurs actions Move ?

public void init(){
circle(ball);
new Move(ball,this,Ball.COSINE).start();
}

résultat


Problème : comment obtenir ce résultat ?

et celui-ci : résultat ?