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那麼必須要返回才能得到數值,而傳一個對象那麼不需要返回就能得到改變。