2012年10月23日星期二

有借有还

有借有还

摘要: 以银行的借贷为例子,描述一格资源租赁的小工具IDBase
关键字: 资源,资源管理,句柄,LIFO

从资源管理的角度看“有借有还”

资源,是相对“废物”而言的反义词。也就是说是有用的东西。有些资源是取之不竭的,有些则是紧缺甚至稀有的。例如:计算机的内存。无论内存条的价格如何每日下跌,内存总是不够用。因为,应用总是对硬件提出更多的要求。不一而足,诸如CPU的运算,硬盘,网络带宽...... 所以使用资源需要有经济学。如何使用资源最为经济,那当然放是共享,而非独占。想象一下一个没有公共交通,全都是私家车的大城市吧。恐怕所有路面都会是停产场。共享,意味着有某个管理者分配资源的使用权,而非分配所有权。其中有种有效的管理方式便是“租借”。如图书馆那般。

用图书馆的方式管理数字空间的物体,同样能起到经济的目的。下面所介绍的IDBase,就是用一个很简单的类,对此作一个“通用”的实现。不要小看“简单”这个词,很多强大的东西,往往都很简单。

资源的“句柄”表述-整数类型ID

我们的这个小小的类叫做 IDBase。资源,自有不同的种类。但这个不应该是我们这个小小的“类”所需要关心的。它仅仅知道,这是某个资源,并给它贴个标签就足够了。资源的种类是 IDBase 的使用者才需要关心的。IDBase 给u每个资源,所贴的标签仅仅是一个唯一的“整数ID”,就足够了。你可以将这个ID看作是一个占位符(Place Holder , Handler)或者其他你认为合适的东西,IDBase 并不关心。

LIFO队列,最简单有效的“出纳员”

IDBase 同样不关心这些借出借入的 ID 的大小顺序,它仅仅关心,这些 ID 是否“唯一”。因此,我们为 ID 的“银行”安排有个最简单但可靠的出纳员 LIFO 队列。这就是 LIFO队列 的实现。这是最为简单的LIFO实现,这里有更为通用的实现,有兴趣来看看吧《队列笔谈:队列的概念、种类和图论应用》。

	private int mMaxID = 0;	private int mStackSize = 0;	private int[] mStack;	...	public int Borrow( ){		if( mStackSize == 0 ) return mMaxID ++;		else return mStack[ --mStackSize ];	}	public void Return( int id ){		mStack[ mStackSize++ ] = id;	}

mStack 是存放 ID 的“银行”,是一个一维整形数组。mMaxID 标记这个 “银行” 曾经达到的最高“贷款”量,也等同于最大的“借出” ID 数值。 mStackSize 则是“银行”当前的“存款”量。mStackSize 是指向 mStack 数组的指针——当前的指针。

先看看 Borrow 函数。 mStackSize == 0 ,表示“银行”的存款已经枯竭 ,于是从“央行”转入新的存款,于是有了 mMaxID ++。否则,从“银行”存款中拨出,于是 --mStackSize 。也就是说 mStack 的当前指针往下拨一格。再看看 Return 函数。 贷款者向银行还钱,于是 mStackSize++ ,同时将所还的钱(ID)存入银行,等待下一个贷款者。

这就是主要的逻辑,再简单不过了。你如果在意多线程的安全问题,可简单在这两个函数里面加上 look( this ){ ... }之类的锁。

下面是整个类的完整实现。

	public class IDBase{		private int mMaxID = 0;		private int mStackSize = 0;		private int[] mStack;				public int BorrowedCount{			get{				return mMaxID - mStackSize;			}		}					public IDBase( int mCapacity ){			this.mStack = new int[ mCapacity ];		}		public int Borrow( ){			if( mStackSize == 0 ) return mMaxID ++;			else return mStack[ --mStackSize ];		}		public void Return( int id ){			mStack[ mStackSize++ ] = id;		}		public void Reset( ){			mMaxID = 0;			mStackSize = 0;					}	}

原文出处: 《极超记忆》
TAG: