号外:kitjs官方讨论QQ群建立了,QQ群号88093625,欢迎大家加入,讨论前端相关话题
今天给大家介绍一下kitJs的多线程类,以及原生的javascript,不借助浏览器插件以及HTML5的webWorker是如何实现多线程模式的。
Demo地址:http://xueduany.github.com/KitJs/KitJs/index.html#multithread
(一)多线程简单工作原理
所谓多线程,一般意义上理解,就是两段程序块,在操作系统的分时调配下,交错运行。
1. 每个程序块需要有自己独立的线程运行环境以及独立上下文
2. 每个程序块包含多个语句块,每个语句块是原子的,不可分割的,例如while之类的循环
3. 语句块和语句块之间是可以分割执行的,以及支持sleep,比如a=1;b=2;这样是两个语句块
4. 程序块可以调用公共资源区,比如调用window空间下其他资源
5. 支持死循环解锁,即杀死进程
(二)Kit是如何实现的
首先我们通过$kit.multithread.newThread方法创建一个新的线程
newThread方法接受一个匿名函数,我们可以看到在这个匿名函数体内部,包含了独立线程块自己的资源,变量a/b,以及自己的逻辑
$kit.multithread.iterate方法提供一个循环方法,类似while,接受2个参数,参数1为一个是否执行循环的标记,参数2为一个循环体。
我们可以看到线程1的循环体的意思就是一个死循环,不断的输出“数字a为xxx”这样的文字
在循环体内部,有一个sleep方法,是让程序块休眠指定的时间,这里是100毫秒
线程2的意思就是b的递减,输出字段,然后有两个判断,当b<995,kill线程1,当b<980时kill自己
最后就是线程定义完毕之后,执行方法
运行页面,我们就会看到线程1和线程2交织执行
(三)原理解析
查看kit源代码,我们可以看到
新建一个线程,kit会保留线程的id号以及线程对应的匿名方法
运行比较简单,直接执行
延时的实现,使用setTimeout做延时,这里有个技巧,在setTimeout里面用匿名方法纠正this指针,同时在线程的附属信息里面记录延时执行的stack顺序
循环的实现,最为复杂,可以看到首先保留远程执行方法的上下文,定义一个inner Fn执行第一次方法体,然后用setInterval执行后续,在setInterval内部还要加载对于sleep的延时判断,如果当前excuteStack处于sleep状态,那么继续hold,等待sleep结束再继续循环
杀死线程,清空所有的excuteStack里面的timeout,delete线程注册信息
(四) 高级技巧
其实对于一个js程序块来说,按照$kit提供的api改成这样已经看上不去很不像一段简单的js代码了
如果要做的更友好一些,我们可以使用正则表达式做一个词法分析器,通过fn.toString获取function的代码块文本,分析,并转换for语句,while语句成为$kit的iterate语句,直接转换sleep(xxx);为$kit的sleep方法,这样的代码会写的更友好一些,这里只为抛砖引玉,欢迎有兴趣的同学继续改成$kit的多线程类,这里也提供了一个parse方法,没有实现