Android游戏前后台切换,游戏循环选重建线程还是wait/notify?用哪组生命周期?
Android 游戏前后台切换的游戏循环处理方案
当用户将你的游戏切到其他应用、再切回前台时,游戏循环的线程状态处理有两种常见实现路径:
- 停止并重建游戏循环线程
- 基于
wait()和notify()机制实现线程暂停、恢复
两种方案的参考实现
方案1:停止并重建线程
// 游戏循环核心执行逻辑 public void run() { while (isRunning) { // 帧更新、输入响应、画面渲染等游戏逻辑 } } @Override protected void onPause() { boolean retry = true; gameLoop.setRunning(false); while (retry) { try { mainThread.join(); retry = false; } catch (InterruptedException e) { e.printStackTrace(); } } super.onPause(); } @Override protected void onResume() { if (gameLoop.isRunning()) { stop(); } gameLoop.setRunning(true); mainThread = new Thread(gameLoop); mainThread.start(); super.onResume(); }
方案2:wait/notify 实现暂停恢复
// 游戏循环核心执行逻辑 public void run() { while (!mFinished) { // 帧更新、输入响应、画面渲染等游戏逻辑 synchronized (mPauseLock) { while (mPaused) { try { mPauseLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } @Override protected void onPause() { synchronized (mPauseLock) { mPaused = true; } super.onPause(); } @Override protected void onResume() { synchronized (mPauseLock) { mPaused = false; mPauseLock.notifyAll(); } super.onResume(); }
方案优劣对比
整体来看方案2的实现更优,核心原因:
- 减少不必要的资源开销:方案1每次前后台切换都要创建、销毁一次游戏线程,线程本身的创建和回收都会占用CPU和内存资源,在低端机型上频繁切换时感知明显。
- 降低状态管理复杂度:方案2的线程对象会一直存活,游戏内部的变量、渲染上下文状态都可以连续保留,不需要在暂停时临时序列化状态、重启时再反序列化恢复,减少了额外的开发工作量。
- 避免主线程阻塞风险:方案1中通过
join()等待线程退出的逻辑,无法控制等待时长,如果游戏循环刚好卡在渲染、IO等耗时操作上,很容易阻塞主线程触发ANR。
方案2的实现需要注意两个细节:
- 必须用
while循环判断mPaused状态,不能用if判断,规避Java线程的虚假唤醒问题。 notifyAll()的调用必须放在同步锁块内,保证锁的获取和释放顺序符合Java并发规范。
生命周期回调的选择
不存在绝对通用的选择标准,核心看你的游戏场景需求:
- 如果游戏切到后台后完全不需要运行任何逻辑(比如普通单机游戏,切后台就需要暂停计时、暂停动画),优先在
onPause()中执行线程暂停、onResume()中执行线程恢复。因为onPause()是系统保证应用进入后台前一定会执行的回调,执行时机更早,能避免切后台后短时间内游戏仍在运行逻辑被系统判定为异常资源占用。 - 如果游戏需要在半可见场景下持续运行逻辑(比如画中画模式、多窗口模式下仍然需要渲染基础画面、更新简单动画),可以把暂停逻辑放到
onStop()、恢复逻辑放到onStart()。因为onStop()是应用完全不可见时才会触发的回调,半可见状态下游戏逻辑会持续运行,匹配这类场景的需求。
内容的提问来源于stack exchange,提问作者Alex Parvan
相关产品推荐
相关产品推荐

