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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章