Я программирую очень простую симуляцию, которая должна изменять цвета поля на доске w
x h
. Каждое поле на доске - это отдельная нить, которая меняет свой цвет каждые случайные миллисекунды. Дело в том, что через некоторое время он просто перестает меняться. Что-то не так с моим кодом, или это вещь оптимизации, или что-то еще? Это какой-то тупик? (Количество потоков ничего не меняет, просто время после остановки отладочной платы составляет 25x25)
Я также обнаружил, что проблема в функции AverageColor () может быть связана с тем, что без нее она работает нормально (например, со статическим цветом вместо среднего)
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();
}
}
}
Остальные в классе:
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();
}
}
}
}
Создано и начато с:
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();
}
}
}
}
В основном:
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();
}