AS3多线程入门(下):多线程编程入门

AS3的多线程和Java的不同,程序员需要在同一个类中判断当前是在主线程还是在分支线程,然后进行操作。

判断Worker.current.isPrimordial这个量:

if(Worker.current.isPrimordial)
{
//这里是主线程
}
else
{
//这里是分支线程
}

假设我们还是上一篇文章的那个情况,在HelloWorldWorker类里,我们需要一个对象级的变量,用protected var worker:Worker;,然后添加Added To Stage事件及其处理代码:

public function HelloWorldWorker()
{
this.addEventListener (Event.ADDED_TO_STAGE,init);
}

private function init(e:Event=null):void
{
removeEventListener (Event.ADDED_TO_STAGE,init);
}
在init函数的末尾加上:

if(Worker.current.isPrimordial){
//这里是创建分支线程,注意parent对应的是主类(Main)的对象
worker = WorkerDomain.current.createWorker(parent.loaderInfo.bytes);

//启动worker线程,worker就是对象变量的那个worker
worker.start();

}
else {

}

这时候,这个类就可以创建分支线程了,但是目前我们还看不到分支线程在做什么。让我们再看看一些内容。

setSharedProperty()和getSharedProperty()
这两个类似于Web编程的Session,可以用worker.setSharedProperty(“key”, value);还分享数据,在另一头用Worker.current.getSharedProperty("key");来获取数据。

MessageChannels
MessageChannels用于消息传递,在一头使用相关的channel.send()方法,另一头就会触发一个Channel Message事件,使用channel.receive()还可以获取发来的数据。

这里贴上我修改的一个示例代码:

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.MessageChannel;
import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.utils.setInterval;

public class HelloWorldWorker extends Sprite
{
protected var mainToWorker:MessageChannel;
protected var workerToMain:MessageChannel;

protected var worker:Worker;

public function HelloWorldWorker()
{

this.addEventListener (Event.ADDED_TO_STAGE,init);
}

private function init(e:Event=null):void
{
removeEventListener (Event.ADDED_TO_STAGE,init);
/**
* Start Main thread
**/
if(Worker.current.isPrimordial){
//Create worker from our own loaderInfo.bytes
worker = WorkerDomain.current.createWorker(parent.loaderInfo.bytes);

//Create messaging channels for 2-way messaging
mainToWorker = Worker.current.createMessageChannel(worker);
workerToMain = worker.createMessageChannel(Worker.current);

//Inject messaging channels as a shared property
worker.setSharedProperty("mainToWorker", mainToWorker);
worker.setSharedProperty("workerToMain", workerToMain);

//Listen to the response from our worker
workerToMain.addEventListener(Event.CHANNEL_MESSAGE, onWorkerToMain);

//Start worker (re-run document class)
worker.start();

//Set an interval that will ask the worker thread to do some math
setInterval(function(){
mainToWorker.send("");
}, 1000);

}
/**
* Start Worker thread
**/
else {

//Inside of our worker, we can use static methods to
//access the shared messgaeChannel's
mainToWorker = Worker.current.getSharedProperty("mainToWorker");
workerToMain = Worker.current.getSharedProperty("workerToMain");
//Listen for messages from the mian thread
mainToWorker.addEventListener(Event.CHANNEL_MESSAGE, onMainToWorker);
}

}

//Main >> Worker
protected function onMainToWorker(event:Event):void {
workerToMain.send("你好");
}

//Worker >> Main
protected function onWorkerToMain(event:Event):void {
trace("从分支线程发来的消息是\""+workerToMain.receive()+"\"");
}
}
}

运行后,Output面板输出“从分支线程发来的消息是"你好"”。

参考文章:http://bbs.9ria.com/thread-144587-1-1.html

到这里,有一个问题值得思考,那就是如果需要多个种类的线程处理对象时,应该怎么做?

一种简单且绝对可行的方法就是使用多个类似HelloWorldWorker这样的类,这样绝对可行,而且非常简单。

还有一种巧妙的方法,那就是HelloWorldWorker类只有一个,但是主线程要先给分支线程用setSharedProperty()或者MessageChannels的send()发送一个字符串,然后分支线程根据这个字符串做相应的事情,也可以把这个字符串引用放在对象级别的变量位置保存,然后再根据这个字符串判断该做什么,也可以在HelloWorldWorker的构造方法中添加这个形参。这种方法把代码都放在了一个类里边,通过变量来选择应该使用哪些代码。这种方法也请感兴趣的读者自行尝试。

还有一种方法就是把HelloWorldWorker这个类组合多个Worker类型的引用,然后为它们设置相应的MessageChannels,和Channel Message事件处理函数,这种方法读者可以自行尝试。如果这些个Worker使用的代码是不一致的,就也用一个变量来判断;如果是一致的,就直接使用所有的代码即可。

还有一个问题值得查阅,那就是如果我们想把对象从主线程传到分支线程,用setSharedProperty()和MessageChannels的send()两种方式哪个合适?笔者现在也没有试过,请读者自行尝试即可。

这里再次提醒一下,AS3中基础类型一般为传值,类类型为传引用,也就是如果传一个int那么必须要返回才能得到数值,而传一个对象那么不需要返回就能得到改变。

发布了81 篇原创文章 · 获赞 18 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章