gpt4 book ai didi

java - 与 Android 中的 GLThread 同步

转载 作者:行者123 更新时间:2023-11-29 22:02:22 29 4
gpt4 key购买 nike

我正在使用 opengl-es 在 android 中使用多线程制作游戏:

class World{

protected static final AtomicInteger entityLock = new AtomicInteger();

private GameEntity entities[];

public World(){
// populate game world with entities
// executed on main thread
addEntity(new GameEntity("tank"));
addEntity(new GameEntity("rifleman"));
addEntity(new GameEntity("rifleman"));
}

void update(){
synchronized(entityLock){
for(int i = 0;i<entities.length;i++){
// move entity to new position
// executed on PhysThread
entities[i].updatePosition();
}
}
if(entity.isDead(){
// remove entity. Enter sync block inside removeEntity() method
removeEntity(entity);
}
}

void draw(GL10 gl){
synchronized(entityLock){
for(int i = 0;i<entites.length;i++){
// draw models
// executed on GLThread
Vector3 entityPosition = entities[i].getPosition();
gl.glTranslatef(entityPosition.x, entityPosition.y, entityPosition.z);
entities[i].draw();
}
}
}

public void addEntity(GameEntity entity){
synchronized(entityLock){
// arrays stuff
}
}

public void removeEntity(GameEntity entity){
synchronized(entityLock){
// arrays stuff
}
}

}

class MyRenderer implements GLSurfaceView.Renderer{

World world;

public MyRenderer(World world){
this.world = world;
}


public void onDrawFrame(GL10 gl) {
// executed on GLThread
world.draw(gl);
}


}

class PhysThreadRunnable implements Runnable{

private long tickRate = 30;

private World world;

private PhysThreadRunnable(World world){
this.world = world;
}

protected void setTickRate(long tickRate){
this.tickRate = tickRate;
}

public void run() {
while(true){
try {
// executed on PhysThread
world.update();
Thread.sleep(1000/tickRate);
} catch (InterruptedException e) {
return;
}

}
}
}

MyActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
World world = new World();
// sets up the game world, populates it with entities

// set up GLSurfaceView (simplified)
setContentView(R.layout.main);
GLSurfaceView mGLView = findViewById(R.id.myGLSurfaceView);
mGLView.setRenderer(new MyRenderer(world));

// start phys thread
PhysThreadRunnable physThreadRunnable = new PhysThreadRunnable(world);
Thread physThread = new Thread(physThreadRunnable);
physThread.start();
}
}

我有一个问题,有时(但不是每次)当我开始游戏时,PhysThread 卡住等待锁被释放(即当我去调试和暂停线程时,它只是坐在 synchronized(entityLock) inside update()

真正奇怪的是,一段时间后(2 秒到 1 分钟之间),PhysThread 将被解除阻塞,游戏将继续进行,而不会在线程循环的多次迭代中任何线程被锁定。 (即游戏运行良好)

编辑:我在示例中添加了一些额外的内容,以防万一这是问题的原因。基本上,更新和绘制实体数组而不是单个实体

最佳答案

我认为这里的问题可能是“同步” block 无法保证公平。

OpenGL 线程将始终连续渲染,因此它会在完成后立即尝试重新进入 onDraw。由于允许哪个线程进入同步块(synchronized block)的选择是任意的,因此 OpenGL 线程可能会在将锁释放给物理线程之前尝试重新获取锁,并根据一些任意标准将锁授予它并在不允许物理线程进入的情况下结束。

这可以解释为什么它有时会发生而不是其他,因为这是一个任意的决定。

您可以尝试实现公平锁而不是同步块(synchronized block),或者使 OpenGL 自上次物理更新后不会多次尝试重绘场景(让渲染线程 hibernate 直到发生更新).

关于java - 与 Android 中的 GLThread 同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11639734/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com