// 2012.3.31
1【缓存 + 同步】确实是一种解决方案
但是我们会发现需要用这种方式的处理的地方很多,多线程下,需要保证线程安全的地方很多,这无疑给程序增加非常多的复杂度。
2 【缓存按键】
其实也可以反过来想想,在同一个线程里切换View,而可能发生View切换的地方其实是按键 onTouch()里,这时候我们需要处理的就是把按键缓存下来,然后在update()之前处理按键就行。
PS:当然一些非常耗时的操作还是需要另起线程,这个时候一般都需要一些变量来标示是否已加载完之类的。
实际用起来可以两者结合,缓存按键不够的话再加上 同步机制
目前我想到的解决线程不同步问题的方法:
I 条件判断
/**
* 解决多线程切换View时线程不同步的问题
*/
public static boolean hasInit;
public GameView currentView;
public void paint(Graphics g) {
if(!hasInit) {
return;
}
currentView.paint(g);
}
public void update() {
if(!hasInit) {
return;
}
currentView.update();
}
public static boolean isRunning = true;
public void run () {
while (isRunning) {
update();
paint(g);
}
}
public void switchState(GameView view) {
hasInit = false;
// 释放上个View的资源
currentView.freeRes();
currentView = view;
// load新View的资源
currentView.init();
hasInit = true;
}
public abstract class GameView {
public abstract void init();
public abstract void freeRes();
public abstract void paint(Graphics g);
public abstract void update();
}
多个线程访问switchState跳转状态时,主线程run还在跑,而另外一个线程跳转状态时会出现:
currentView.freeRes(); 当前资源已经释放,主线程却还在用的情况。
currentView.init();新的View还没初始化完,主线程却已经开始用。
用hasInit 来限制这段释放老资源load新资源的时间,比避免NullPointer的问题。
II 缓存机制
以上方法只是表面上可行,其实根本上并没有解决问题,只是在一定程度上降低了几率而已
/**
* 缓存机制来
* 解决多线程切换View时线程不同步的问题
*/
public void paint(Graphics g) {
currentView.paint(g);
}
public void update() {
currentView.update();
}
public static boolean isRunning = true;
public void run () {
while (isRunning) {
ViewManager.changeView();
update();
paint(g);
}
}
/**
* 界面基类
* @author wangxueping01
*/
public abstract class GameView {
public abstract void init();
public abstract void freeRes();
public abstract void paint(Graphics g);
public abstract void update();
}
/**
* 界面管理
* @author wangxueping01
*/
public class ViewManager {
/** 当前的View */
public static GameView currentView;
/** 缓存的View */
public static GameView cacheView;
/**
* 缓存跳转的状态View
* @param view
*/
public static void switchView(GameView view) {
cacheView = view;
}
/**
* 每帧最开始调用
*/
public static void changeView() {
if (cacheView != null && cacheView != currentView) {
currentView = cacheView;
// 释放上个View的资源
currentView.freeRes();
currentView = view;
// load新View的资源
currentView.init();
}
cacheView = null;
}
}
switchView 和 changeView 应该是互斥的。
但是对游戏来说,速度第一位。
目前采用第二种 同步机制需要进一步研究
III 同步机制
给互斥的方法加上synchronized
public class ViewManager {
/** 当前的View */
public static GameView currentView;
/** 缓存的View */
public static GameView cacheView;
/**
* 缓存跳转的状态View
* @param view
*/
public static synchronized void switchView(GameView view) {
cacheView = view;
}
/**
* 每帧最开始调用
*/
public static synchronized void changeView() {
if (cacheView != null && cacheView != currentView) {
currentView = cacheView;
// 释放上个View的资源
currentView.freeRes();
currentView = view;
// load新View的资源
currentView.init();
}
cacheView = null;
}
}
链接