我在我的游戏中有一个设置,物理在一个单独的线程中更新,实现如下
物理处理器(物理线程)
public class PhysicsProcessor extends Runnable {
private DynamicsWorld world;
public PhysicsProcessor() {
/* basic dynamics world setup with dvbt broadphase :P */
}
public synchronized getDynamicsWorld() { return world; }
@Override
public void run() {
/* update time */
//update phyics
getDynamicsWorld().stepSimulation(/* delta time */);
}
}在主线程中创建对象示例
myPhysicsProcessor.getDynamicsWorld.addRigidBody(/* some rigid body created here */);问题是,当游戏运行时,我偶尔会在"stepSimulation“上的单独线程中得到一个空指针异常,这是由我的dbvt宽阶段中的setAabb引起的。
有没有人有什么建议,我可以做些什么来防止这种异常,或者如何解决它?
发布于 2014-05-07 06:06:18
从外观上看,你可以让这个世界变得final。然后这将向您展示同步访问的无用之处:
public class PhysicsProcessor extends Runnable {
private final DynamicsWorld world;
public synchronized DynamicsWorld getDynamicsWorld() { return world; } //why sync? it can't change
}您可以看到,当您执行以下操作时:myPhysicsProcessor.getDynamicsWorld().addRigidBody(...)在getDynamicsWorld()返回后同步停止。因此,在安全同步上下文之外调用addRigidBody(...)。
不,您要做的是确保在a sync块中始终使用它:
@Override
public void run() {
//update physics
synchronized(this) {
world.stepSimulation(/* delta time */);
}
}
public void addBody(/*args here*/) {
synchronized(this) {
world.addRigidBody(/*args here*/);
}
}现在这对于一种方法来说是可以的,但是如果你发现自己想要用这种方式在runner之外做很多DynamicsWorld方法,或者只是想要另一种选择,那么这个方法不需要同步:
public interface IWorldRunable {
void run(DynamicsWorld world);
}
public class PhysicsProcessor extends Runnable {
private final DynamicsWorld world;
private final ConcurrentLinkedQueue<IWorldRunable> worldRunables = ConcurrentLinkedQueue<IWorldRunable>();
public PhysicsProcessor() {
/* basic dynamics world setup with dvbt broadphase :P */
}
@Override
public void run() {
/* update time */
//run runables on world
for(IWorldRunable runable : worldRunables)
runable.run(world);
//clear runables
worldRunables.clear();
//update phyics
world.stepSimulation(/* delta time */);
}
public void do(IWorldRunable runnable) {
worldRunables.add(runnable);
}
}然后,您将执行以下操作,以添加body:
myPhysicsProcessor.do(new IWorldRunable(){
@Override
public void run(DynamicsWorld world){
world.addRigidBody(...);
}
});它将在同一线程上的下一个stepSimulation之前执行,所以不用担心线程。
https://stackoverflow.com/questions/23481191
复制相似问题