龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

利用AJAX技术实现Web开发中的互斥技术(1)(2)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
Mutex类的基本逻辑是,把每一个新的Mutex实例放到一个顾客等待列表中,然后启动该列表并排队等候。每一次试图(直到最后一个排队者)走到“队伍最前端
Mutex类的基本逻辑是,把每一个新的Mutex实例放到一个顾客等待列表中,然后启动该列表并排队等候。每一次试图(直到最后一个排队者)走到“队伍最前端”都要求等待,这样可以使用setTimeout来调度每一次新的尝试(当前排队者已经离开后才开始)。当到达最前端时(见上面的第17行),互斥存取成功;因此,临界区方法被调用。当执行完临界区后,释放存取权,并且把Mutex实例从等待列表中删除(第20~21行)。
Mutex构造器(第23~31行)记录它的Command对象和方法名参数,然后把它自己注册到一个正在进行的(Mutex.Wait)临界区稀疏数组,这是经由Map类实现的,如列表4所示。然后,它得到“下一个序号”并开始在最后一行等待。由于等待序号中不存在间断和重复的情况,所以当前的时间戳实际上被用作“下一个”序号。
attempt()方法把原始伪码中的两个等待循环结合到单个循环(直到等到列表最前端才进入临界区中)。这个循环是一种“忙等待”形式的查询,通过以指定的延迟时间来调用setTimeout()即可以“打破”此等待。既然setTimeout要求调用一个“普通函数”而不是一个对象方法,那么在第4~6行定义了一个静态的助理方法(Mutex.SLICE)。SLICE在顾客等待列表中定位指定的Mutex对象并且调用它的attempt()方法(它的开始参数用于指定,到目前为止,它进入到等待列表已有多长时间)。每一个SLICE()调用都相当于得到一个“CPU时间片”。这种移交CPU控制权的协作方式(经由setTimeout)以前被称作协同程序。

function Map() {
this.map = new Object();
//Map API
this.add = function( k,o ){
this.map[k] = o;
}
this.remove = function( k ){
delete this.map[k];
}
this.get = function( k ){
return k==null ? null : this.map[k];
}
this.first = function(){
return this.get( this.nextKey() );
}
this.next = function( k ){
return this.get( this.nextKey(k) );
}
this.nextKey = function( k ){
for (i in this.map) {
if ( !k ) return i;
if (k==i) k=null; /*技巧*/
}
return null;
}
}

列表4.实现为一个Map数据结构的稀疏数组

五、RIA集成

既然Mutex能够处理动态数目的线程(虚拟的或非虚拟的),那么我们可以得出这样的结论:既然“浏览器对每个浏览器事件都赋予一个独立的线程”,那么,我们无法知道一个实际线程的ID。一个类似的简化的假设是,每个complete事件处理器都组成一个完整的临界区。这样的话,每个事件处理器函数就可以被转换成一个Command对象,并且可以使用Mutex来调用和管理它们。当然,如果代码还没有被整洁地组织到事件处理函数中,那么必须对之进行重构。换句话说,不是直接在HTML事件属性(例如,onclick='++var')中实现编码逻辑,而是定义并调用事件处理函数(例如,onclick='FOO()'和函数FOO(){++var;})。







列表5.具有非同步事件处理器的示例web页面

如列表5所示,假定共有3个事件处理器函数―它们都操作共同的数据。它们分别处理一个page-load事件,一个button-click事件和一个request-reply(接收XML请求并响应)事件。page-load事件处理器启动某种异步数据请求。它指定request-reply事件处理器―由它来处理接收的数据并把它加载到一个共享数据结构中。button-click处理器也影响这个共享数据结构。为防止这些事件处理器发生冲突,可以把它们转换成Command对象并使用Mutex来激活,如列表6所示。(假定Map和Mutex都包含在JavaScript包括文件mutex.js中)。注意,虽然可以使用良好的类继承机制来实现Command子类,但是这里的代码只展示了一种最小实现―仅使用了全局变量NEXT_CMD_ID。








列表6.被转换为同步事件处理器的Web页面

三个事件处理器函数都被转换以实现通过Mutex调用其原先的逻辑(现在,每个函数都被包装到Command类中)。每个Command类定义唯一的ID和一个包含临界区逻辑的方法,从而实现Command接口要求。

六、结论

随着AJAX技术和RIA技术的出现,Web开发者尝试使用与以前构造“胖”GUI客户端相同的设计模式(例如,模型-视图-控制器)来构建复杂的动态用户接口。通过把视图和控制器用模块化定义,每一部分都有其各自的事件和事件处理器(但共享共同的数据模型),这将会成倍地提高冲突的可能性。通过把事件处理逻辑封装到Command类中,我们不仅可以使用Wallace改进算法,而且可以为程序提供丰富的“撤消/恢复”功能,脚本接口以及单元测试工具。

参考信息

•本文中的示例共包含5个文件。其中包括被省略的细节―Web页面能够直接在浏览器中执行而不要求一个服务器连接。
•另外一个JavaScript框架(Gravy)也使用了本文中相应的技术,你可以查看或下载之,这个链接还提供了完整的JsDoc参考文档。Gravy支持把所有的应用程序功能都放在浏览器端的JavaScript中,应用程序仅仅需要存取服务器来实现数据库CRUD操作。

(责任编辑:铭铭 mingming_ky@126.com TEL:(010)68476606)
精彩图集

赞助商链接