多线程切换View时线程不同步的问题---游戏状态跳转管理

// 2012.3.31

1【缓存 + 同步】确实是一种解决方案

但是我们会发现需要用这种方式的处理的地方很多,多线程下,需要保证线程安全的地方很多,这无疑给程序增加非常多的复杂度。

【缓存按键】

其实也可以反过来想想,在同一个线程里切换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;   
    }  
}  

链接   

synchronized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值