我尝试了点和线的碰撞模拟。通过将point无限地加1到point.x和point.y来移动点。主线程立刻检查两个对象之间的冲突。如果该点碰撞到该线,它将停止。它工作得很好,但是会发生一些错误。如果主线程无延迟循环,则检查方法的结果始终返回“ False”(以防绝对返回“ True”)。在以下某些情况下没有错误。
为什么会这样?
[主线程]
public static void main(String[] args) throws IOException {
DrawingFrame d = new DrawingFrame();
PointObject p = new PointObject(200,200);
LineObject l = new LineObject(100,10,new Vector(500,Math.toRadians(60.0f)));
p.move();
d.addDrawable(p);
d.addDrawable(l);
while(true) {
// if main thread loops infinitely without delay,
// the result of checking method always returned 'False'.
// System.out.println(); <-- DELAY
if(l.isAbove(p)) p.stop=true;
}
}
[移动]
public void move() {
new Thread(new Runnable() {
@Override
public void run() {
while(!stop) {
x++;
y++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
[检查]
@Override
public boolean isAbove(PointObject p) {
return Math.abs(p.y-(Math.tan(this.vector.radian)*(p.x-this.x)+this.y))<=ERROR;
}
答案 0 :(得分:0)
因此,答案是您没有花时间让新线程进行迭代。 我简化了您的方法,例如
public void main() {
PointObject p = new PointObject(1, 1);
LineObject l = new LineObject(5, 5);
p.move();
// d.addDrawable(p);
// d.addDrawable(l);
while (true) {
System.out.println("Thread - "+Thread.currentThread().getName() + ": in while p.x =" + p.x + " p.y=" + p.y);
if (l.isAbove(p)) {
p.stop = true;
break;
}
}
}
public class PointObject {
int x;
int y;
boolean stop = false;
public PointObject(int x, int y) {
this.x = x;
this.y = y;
}
public void move() {
Thread thread = new Thread(
new Runnable() {
@Override
public void run() {
while (!stop) {
x++;
y++;
try {
System.out.println("Thread - "+Thread.currentThread().getName() + ": in move x =" + x + " y=" + y);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.setName("MY-THREAD");
thread.start();
}
}
public class LineObject {
int x;
int y;
int iteration;
public LineObject(int x, int y) {
this.x = x;
this.y = y;
this.vector = vector;
}
public boolean isAbove(PointObject p) {
System.out.println("Thread - "+Thread.currentThread().getName() + ": in isAbove x = " + x + " y= " + y);
int result = p.y + p.x - (this.x + this.y);
System.out.println("result = " + result);
System.out.println("iteration = " + iteration++);
return result > 0;
}
}
所以,您可以看到直到第102次迭代
Thread - main: in while p.x =1 p.y=1
Thread - main: in isAbove x = 5 y= 5
Thread - MY-THREAD: in move x =2 y=2
result = -6
iteration = 1
只有在这里(第103次迭代)我们才能看到
Thread - main: in while p.x =3 p.y=3
Thread - main: in isAbove x = 5 y= 5
result = -4
iteration = 103
Thread - main: in while p.x =3 p.y=3
Thread - main: in isAbove x = 5 y= 5
实际上,我不知道您如何从while(true)
循环中逃脱以及如何获得stop = true。如您所见,我仅在第60次迭代中进行了一些更改。因此,正如它所说的,您应该为多线程创建同步/睡眠/池/队列。
在布尔值中没有volatile,布尔值在评论中说我有3000+次迭代,但有了它我就有1700+次。无论如何,我们发现了您的问题。
首先,您不能逃脱while(true)
,应使用
在pause
上添加一些while(true)
,以使其他Thread开展业务
答案 1 :(得分:0)
您的问题很可能是由于Point.x
,Point.y
和Point.stop
不稳定而被多个线程读取而造成的。该线程可能会缓存非易失性成员,并且永远不会看到另一个线程所做的更改。简而言之,如果您要确保可以从另一个线程看到对一个线程所做的字段所做的更改,则需要使字段volatile
。请参考以下问题:What is the volatile keyword useful for。
另一个提示(与您遇到的问题无关):您缺乏关于Point.x
和Point.y
更改的同步-这可能导致Point.x
和Point.y
不一致读取(通过在isAbove
之后但在x++;
之前调用y++;
),我认为这不是您想要的。简单的锁定示例:
在move()
中:
synchronize(this) {
x++; y++;
}
在main()
中:
synchronize(p) {
if(l.isAbove(p)) p.stop = true;
}