forked from: そうめんで Queue とか
そうめんのサンプル FlickrSphere にある PhotoImageQueue が便利なので、
なるだけ解りやすくシンプルにしてみたサンプル作ってみたよ。
@see http://www.libspark.org/browser/as3/Thread/trunk/samples/flickrsphere/src/org/libspark/flickrsphere/threads/flickr/PhotoImageQueue.as
// forked from soundkitchen's そうめんで Queue とか
/**
* 複数のスレッドでキューにアクセスする感じにしてみた。notify();ってこういう場面に良いわけですね。
*
* @see http://www.libspark.org/browser/as3/Thread/trunk/samples/flickrsphere/src/org/libspark/flickrsphere/threads/flickr/PhotoImageQueue.as
*/
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import org.libspark.thread.EnterFrameThreadExecutor;
import org.libspark.thread.Thread;
[SWF(frameRate=30, width=465, height=465, backgroundColor=0xffffff)]
/**
* ドキュメントクラス
*/
public class Tmp extends Sprite
{
/**
* コンストラクタ
*/
public function Tmp()
{
// ステージ上で会いましょう
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
/**
* 初期化する
*/
private function initialize(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initialize);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// そうめんの初期化がまだなら
if (!Thread.isReady)
{
// ココで初期化しませう
Thread.initialize(new EnterFrameThreadExecutor());
}
// ではではタスクを消化しましょう!!
new MainThread(this).start();
}
}
}
import flash.display.DisplayObjectContainer;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import org.libspark.thread.Monitor;
import org.libspark.thread.Thread;
/**
* メイン処理を行うスレッド
*/
internal class MainThread extends Thread
{
private var layer:DisplayObjectContainer;
/**
* コンストラクタ
*/
public function MainThread(layer:DisplayObjectContainer)
{
this.layer = layer;
}
/**
* 最初に実行される処理
*/
override protected function run():void
{
var queue:SimpleQueue,
fmt:TextFormat,
txt:TextField;
fmt = new TextFormat();
fmt.size = 96;
fmt.bold = true;
fmt.font = 'sans-serif';
fmt.color = 0x4c4c4c;
txt = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.selectable = false;
txt.defaultTextFormat = fmt;
layer.addChild(txt);
// タスクを管理するキューを作成
queue = new SimpleQueue;
// タスクを作るスレッドを起動
new StackTaskThread(queue, .8).start();
// タスクを消化するスレッドを起動
new OutputTaskThread(queue, txt).start();
// タスク消化スレッドを起動 その2
new OutputColordThread(queue, txt).start();
}
/**
* 後始末する
*/
override protected function finalize():void
{
layer = null;
}
}
/**
* タスクをスタックするキュー
*/
internal class SimpleQueue
{
private var queue:Vector.<String>;
private var monitor:Monitor;
/**
* キューが空かどうかを判別する
*/
public function get isEmpty():Boolean
{
return queue.length == 0;
}
/**
* コンストラクタ
*/
public function SimpleQueue()
{
queue = new Vector.<String>();
monitor = new Monitor();
}
/**
* 消化出来るタスクがあるかを判別する
*/
public function checkPoll():Boolean
{
var retval:Boolean = true;
// キューが空なら
if (isEmpty)
{
retval = false;
// 現在のスレッドを待機させる
monitor.wait();
}
return retval;
}
/**
* タスクを一つ返す
* ココの返り値の型が決められないがために、
* コイツはライブラリ化されてないんだろうなぁ。と思う
*/
public function poll():String
{
// 先頭のタスクを返す
return queue.shift();
}
/**
* 新しいタスクをスタックし、それを消費者にオファーする
*/
public function offer(value:String):void
{
// 与えられたタスクをスタック
queue.push(value);
// 待ち状態のスレッドを起こす
monitor.notify();
}
}
/**
* ひたすらキューにタスクを詰め込むスレッド
*/
internal class StackTaskThread extends Thread
{
private var queue:SimpleQueue;
private var threshold:Number = 0;
/**
* コンストラクタ
*/
public function StackTaskThread(queue:SimpleQueue, threshold:Number=0)
{
// キューを受け取る
this.queue = queue;
// スレッショルドが NaN で無ければ
if (!isNaN(threshold))
{
// 設定に反映する
this.threshold = threshold;
}
}
/**
* 最初に実行される処理
*/
override protected function run():void
{
// 割り込まれてたらおしまい
if (checkInterrupted()) return;
// 乱数が敷居値を越えていれば
if (Math.random() >= threshold)
{
var code:uint;
// 65 ~ 90 -> a - z
code = Math.floor(Math.random() * 26) + 65;
// 適当な文字を一文字タスクに入れる
queue.offer(String.fromCharCode(code));
}
// 次もまたこの処理を呼ぶように登録
next(run);
}
/**
* 後始末する
*/
override protected function finalize():void
{
queue = null;
}
}
/**
* キューにスタックされたタスクを消化するスレッド
*/
internal class OutputTaskThread extends Thread
{
private var queue:SimpleQueue;
private var target:TextField;
private var stage:Stage;
/**
* コンストラクタ
*/
public function OutputTaskThread(queue:SimpleQueue, target:TextField)
{
this.queue = queue;
this.target = target;
this.stage = target.stage;
}
/**
* 最初に実行される処理
*/
override protected function run():void
{
// キューにタスクがスタックされていれば
if (queue.checkPoll())
{
// それをアウトプット
target.text = queue.poll();
// x, y の値をセンターに補正
target.x = (stage.stageWidth - target.width) / 2;
target.y = (stage.stageHeight - target.height) / 2;
}
// 次のタスクを登録する
next(run);
}
/**
* 後始末する
*/
override protected function finalize():void
{
queue = null;
target = null;
stage = null;
}
}
/**
* キューにスタックされたタスクを消化するスレッド その2
*/
internal class OutputColordThread extends Thread
{
private var queue:SimpleQueue;
private var target:TextField;
private var stage:Stage;
private var format:TextFormat;
/**
* コンストラクタ
*/
public function OutputColordThread(queue:SimpleQueue, target:TextField)
{
this.queue = queue;
this.target = target;
this.stage = target.stage;
this.format = target.defaultTextFormat;
this.format.color = '0xff0000';
}
/**
* 最初に実行される処理
*/
override protected function run():void
{
// キューにタスクがスタックされていれば
if (queue.checkPoll())
{
// それをアウトプット
target.text = queue.poll();
target.setTextFormat(this.format);
// x, y の値をセンターに補正
target.x = (stage.stageWidth - target.width) / 2;
target.y = (stage.stageHeight - target.height) / 2;
}
// 次のタスクを登録する
next(run);
}
/**
* 後始末する
*/
override protected function finalize():void
{
queue = null;
target = null;
stage = null;
}
}