我正在编写一个非常简单的模拟,它应该改变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();
}
答案 0 :(得分:0)
只是一些事情:
一个。当上面代码中的q
超过(或匹配)p
的值时,代码将计算平均颜色 - 每次都相同,假设相邻字段没有更改颜色。
B中。导致run
循环退出的异常。我怀疑是这种情况,但您可能希望在调试时捕获所有错误。
答案 1 :(得分:0)
通常,Swing不是线程安全的。必须在事件派发线程上完成对Swing组件方法的任何调用。您可以在Java Tutorials&#34; The Event Dispatch Thread&#34;:https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
中阅读相关内容。答案 2 :(得分:0)
感谢@ cmosher01
从synchronized
getColor
和getSideColor
移除averageColor
来解决问题,但我不知道为什么。如果有人知道,我会理解为什么它可能导致了这个问题。
答案 3 :(得分:0)
你得到的是典型的僵局。
考虑两个Field
的情况,在x = 0,y = 0,B在x = 1,y = 0。
在Field
A尝试计算averageColor()
的某个时间点 - 在此期间它会自行锁定(因为averageColor()
已同步)。此计算的一部分是在getColor(..)
B上调用Field
,并在Field
B上同步。
如果同时Field
B尝试计算其averageColor()
,Field
B会自行锁定(Field
A无法调用getColor(..)
在Field
B)。此计算的一部分依次在getColor(..)
A上调用Field
- 因为Field
A保持对自身的锁定并尝试在{{1上调用getColor(..)
B。