2011-02-09 24 views
3

次の問題を解決する方法を理解できません:私はそれらを受け取ったときに何らかの方法でタスクを実行する少数の俳優(労働者)を持っています。メインの俳優(監督)がこのプロセスをコントロールし、仕事を止めるための仕事を受け取ることができます。この場合、主役は新しい仕事の作成をやめ、従業員が既存の仕事をすべて終えるのを待ってから、主人だけが退場するようにしなければなりません。この問題を解決するには終了する前に子どものすべての仕事を完了するのを待つ俳優

import actors.Actor 
import actors.Actor._ 

class Foreman extends Actor{ 
    val workerA = new WorkerA 
    val workerB = new WorkerB 
    val workerC = new WorkerC 
    self.link(workerA) 
    self.link(workerB) 
    self.link(workerC) 
    def act{ 
    workerA.start 
    workerB.start 
    workerC.start 

    // adding tasks to workers somehow 
    //... 
    loop{ 
     case ResultOfTask(res) => //... 
     case Stop => //workers mustn't immediately stop but must finish their tasks and then exit 
     case ProductionAccident => //... 
    } 


    } 
} 

case class Task(activity:String) 
case class ResultOfTask(result:String) 

trait Worker extends Actor{ 

    def act{ 
    loop{ 
     react{ 
     case Task(activity) => sender ! processTask(activity) 
     } 
    } 
    } 

    def processTask(activity:String):ResultOfTask 
} 

私は、次のコードを書いた:主な俳優が終了しなければならないかどうかを確認するために

def condition = workerA.getState!=State.Suspended && workerB.getState!=State.Suspended && workerC.getState!=State.Suspended && mailboxSize == 0 
case Stop => { 
    if(condition) exit("sweet dreams") else continue 
} 

を。 「ワーカー」特性にカウンターを持つもう1つの変種は、ワーカーがメッセージを受け取ったときにインクリメントし、応答したときにデクリメントすることです。 「フォアマン」の

trait Worker extends Actor { 
    private var count = 0 
    def act { 
    loop{ 
     react{ 
     case Task(activity) => { 
      count += 1 
      sender ! processTask(activity) 
      count -= 1 
     } 
     } 
    } 
    } 
    def hasDoneAllTasks = count == 0 

    def processTask(activity: String): ResultOfTask 
} 

そして「条件」機能私はそこに、より良いソリューションがあり、あなたがそれらを提案することを願っています

def condition = workerA.hasDoneAllTasks && workerB.hasDoneAllTasks && workerC.hasDoneAllTasks && mailboxSize == 0 

になります。

答えて

1

でタスクメッセージ職長は、常に労働者からの回答を期待していた場合は、解決策は簡単です:職長は、カウンタを維持し、それぞれの時間は、それはそれをインクリメントし、メッセージを送信し、それぞれの時間は、それが1を受け取り、作業者からそれを減らす。カウンターがゼロのときはいつでも、自分自身を自由に停止することができます(他に誰もワーカーにメッセージを送信しないと仮定します)。

職長は、常に労働者からの回答を期待していない場合は、

case object Done { } 

無内容のメッセージを有し、それらが終了したら、労働者がそれに答えることによって、この場合行うことができます。その後、上記を参照してください。

職員が労働者に話す唯一の人ではない場合、または職場にチャーターが少ないことを希望する場合は、監督と労働者が交渉しなければなりません。職長は

case object RequestStop { } 

を送ることができますし、労働者は優雅な何かをすると、彼らが完了したら、Doneで返信させていただきます。担当者がRequestStopを送信したときに多くのDoneメッセージを受信すると、それは自由に終了します。

1

作業員にジョブを送信するときに、フォアマン俳優への参照を含めないのはなぜですか?その後、労働者がシャットダウンすると、彼らはフォアマンに通知を送ることができます。フォアマンは、ワーカーがシャットダウンメッセージを受け取るたびにログに記録し、すべてのワーカーが完了したかどうかを確認します。もしそうなら、それ自体も閉鎖されます。

+0

いいえ、労働者はシャットダウンを決めることができません、フォアマンはします。 – Jeriho

+2

これは、提案されたものではありません。労働者は、フォアマンへの言及を持っており、すべてが完了したときにメッセージを送信します。フォアマンは、このメッセージを受け取った労働者を追跡し、適切な時期にシャットダウンします。 – Janx

+0

Janxは私よりも優れていると思う。 – pr1001

1

私のアプローチは、Foremanですべての計算を行うことです。

あなたは職長は、タスクを作成する方法を書いていないので、私はそれがメッセージ

class Foreman extends Actor{ 

    var numTasks: Int = 0 
    var shouldExit = false 

    def act = loop { 
    react { 
    case t: Task => 
     if (!shouldExit) { 
     numTasks += 1 
     selectWorker ! t 
     } else { 
     // send some kind of error status to sender 
     } 
    case ResultOfTask(rest) => 
     numTasks -= 1 
     // .... 
     if (numTasks == 0 && shouldExit) exit 
    case Stop() => shoudExit = true 
} 

に応じて改善が、それが処理されるように存在する場合でも、停止の優先順位を決定することであると仮定しますキュー

def act = loop { 
    reactWithin(0) { 
    case Stop() => shouldStop = true 
    case TIMEOUT => react { 
     case t: Task => 
     if (!shouldExit) { 
      numTasks += 1 
      selectWorker ! t 
     } else { 
      // send some kind of error status to sender 
     } 
     case ResultOfTask(rest) => 
     numTasks -= 1 
     // .... 
     if (numTasks == 0 && shouldExit) exit 
     case Stop() => shoudExit = true 
    } 
} 
1

あなたが利用できることの1つは、trapExit、ケース出口と終了システムです。あなたの主な役者では、trueにtrapExitを設定することができます。

// Foreman 

def act() { 
    trapExit = true 
    link(workerA) 
    link(workerB) 
    ... 
} 

これは、ワーカー・プロセスが終了すると、あなたの職長俳優は理由を含め、終了メッセージが表示されますことを意味します

// Foreman 

def act() { 
    .... 
    loop { react { 
    case Exit (worker: Actor, reason: AnyRef) => { 
     // decrement counter, or list of workers, and exit if empty 
    } 
    ... 
    }} 
} 

あなたがパターンできますreasonパラメーターで一致します。その上

// Worker: 

exit(WorkComplete) 
exit(Emergency) 

など、および:たとえば、あなたのワーカークラスで、あなたは職長が何をすべきかを示すケースクラスのさまざまな方法を使って終了する場合があります。あなたのワーカーが例外をスローすると、それは終了し、リンクされたプロセスに例外を含む終了メッセージを送信します。この種のものを考えると、あなたのようなもので終わることができます。

// Foreman 

def act() { 
    .... 
    loop { react { 
    case Exit (worker: Actor, reason: WorkComplete) => { 
     // decrement counter, or list of workers, and exit if empty 
    } 

    case Exit (worker: Actor, reason: TasksExhausted) => { 
     // log something, or make shut down worker if too many are exhausted 
    } 

    case Exit (worker: Actor, reason: Exception) => { 
     // log the exception, then restart the actor 
    } 

    ... 
    }} 
} 

あなたは労働者は、彼らが終了する必要があり職長がそれらを告げるまで、行われている場合でも、作業に維持したい場合、それはあなたの最初の質問から不明ですそれは時間です。その場合、「終了時に終了する」というメッセージをワーカーに送信し、trapExitメカニズムを使用して完了したことを伝えることができます。

これは興味深いソリューションです。

関連する問題