I'm programming a very simple simulation that is supposed to change field colors on w
x h
board. Each field on the board is a single Thread that changes it's color every random miliseconds. The thing is, after some time it just stops changing. Is there something wrong with my code, or is it optimalization thing, or something else? Is it some kind of deadlock? (Amount of threads does not change anything, just the time after it stops, debug board is 25x25)
I also found out that averageColor() may be causing the problem, becouse it works fine without it (f.e. with static color instead of average)
public void run() {
while( true ) {
try {
int time;
double q;
int newcolor;
synchronized( gen ) { // gen is a Random (one for the whole program)
time = gen.nextInt( k ) + k/2; // k is a given parameter, 200 for debugging
q = gen.nextDouble();
newcolor = gen.nextInt( 256*256*256 );
}
synchronized( this ) { // posting rest of the class below
wait( time ); // replacing with Thread.sleep( time ) does not fix the problem
if( q < p ) { // with p probability it changes color to rando
me.setBackground( new Color( newcolor ) );
}
else { // with p-1 it pick an avarge
me.setBackground( averageColor() ); // averageColor takes an avarge of neighbour fields
}
}
//Thread.yield(); // removed it as wrestang said, but it does not change anything
} catch( InterruptedException e ) {
e.printStackTrace();
}
}
}
Rest of the class:
public class Field extends Thread {
static Panel panel;
Label me;
Random gen;
int x, y, w, h;
int k;
double p;
Field[][] others;
enum Side {
up,
down,
right,
left
}
enum ColorPart {
R,
G,
B
}
Field( Panel panel, Random gen, Field[][] others, int x, int y, int k, double p, int w, int h ) {
this.gen = gen;
this.others = others;
this.x = x;
this.y = y;
this.k = k;
this.p = p;
this.w= w;
this.h = h;
me = new Label();
me.setBackground( new Color( gen.nextInt( 256*256*256 ) ) );
panel.add( me );
setDaemon( true );
}
synchronized int getColor( ColorPart c ) {
switch( c ) {
case B:
return me.getBackground().getBlue();
case G:
return me.getBackground().getGreen();
case R:
return me.getBackground().getRed();
}
return 0;
}
synchronized int getSideColor( Side side, ColorPart c ) {
int a, b;
switch( side ) {
case down:
b = y+1;
while( b >= h ) b -= h;
return others[x][b].getColor( c );
case left:
a = x-1;
while( a < 0 ) a += w;
return others[a][y].getColor( c );
case right:
a = x+1;
while( a >= w ) a -= w;
return others[a][y].getColor( c );
case up:
b = y-1;
while( b < 0 ) b += h;
return others[x][b].getColor( c );
}
return 0;
}
synchronized Color averageColor() {
int r = 0;
int g = 0;
int b = 0;
r += getSideColor( Side.up, ColorPart.R );
r += getSideColor( Side.down, ColorPart.R );
r += getSideColor( Side.right, ColorPart.R );
r += getSideColor( Side.left, ColorPart.R );
r /= 4;
g += getSideColor( Side.up, ColorPart.G );
g += getSideColor( Side.down, ColorPart.G );
g += getSideColor( Side.right, ColorPart.G );
g += getSideColor( Side.left, ColorPart.G );
g /= 4;
b += getSideColor( Side.up, ColorPart.B );
b += getSideColor( Side.down, ColorPart.B );
b += getSideColor( Side.right, ColorPart.B );
b += getSideColor( Side.left, ColorPart.B );
b /= 4;
return new Color( r, g, b );
}
@Override
public void run() {
while( true ) {
try {
int time;
double q;
int newcolor;
synchronized( gen ) {
time = gen.nextInt( k ) + k/2;
q = gen.nextDouble();
newcolor = gen.nextInt( 256*256*256 );
}
synchronized( this ) {
wait( time );
if( q < p ) {
me.setBackground( new Color( newcolor ) );
}
else {
me.setBackground( averageColor() );
}
}
} catch( InterruptedException e ) {
e.printStackTrace();
}
}
}
}
Created and started with:
public class SymPanel extends Panel {
private static final long serialVersionUID = 1L;
Random gen;
int w, h;
int k;
double p;
Field[][] fields;
SymPanel( int w, int h, int k, double p ) {
this.w = w;
this.h = h;
this.k = k;
this.p = p;
setLayout( new GridLayout( h, w ) );
gen = new Random();
Field.panel = this;
fields = new Field[w][h];
for( int j = 0; j<h; j++ ) {
for( int i = 0; i<w; i++ ) {
fields[i][j] = new Field( this, gen, fields, i, j, k, p, w, h );
}
}
}
public synchronized void start() {
for( int j = 0; j<h; j++ ) {
for( int i = 0; i<w; i++ ) {
fields[i][j].start();
}
}
}
}
In main:
public static void main( String[] args ) {
frame = new Frame("Sym");
frame.setBounds( 300, 100, 1024, 768 );
frame.addWindowListener( new Sym() );
sympanel = new SymPanel( 25, 25, 200, 0.3 );
frame.add( sympanel );
frame.setVisible( true );
sympanel.start();
}