4

そのため、非推奨の Thread.stop() のように、何らかの方法で未来を「殺す」方法を尋ねるスタックオーバーフローに関するいくつかの質問を目にします。不可能な理由を説明する回答が表示されますが、同様の問題を解決するための代替メカニズムはありません。

例:先物の実用化?つまり、それらを殺す方法は?

未来を「殺す」ことはできないことに気づきました。

Java の方法でこれを行う方法を知っています。タスクをより小さなスリープに分割し、定期的にチェックされるスレッド クラスに「揮発性ブール値 isStillRunning」をいくつか設定します。この値を更新してスレッドをキャンセルした場合、スレッドは終了します。これには「共有状態」 (isStillRunning 変数) が含まれており、同じことを Scala で行うとしたら、あまり「機能的」ではないように見えます。

慣用的な関数型スカラでこの種の問題を解決する正しい方法は何ですか? それを行う合理的に簡潔な方法はありますか?「通常の」スレッドと揮発性フラグに戻す必要がありますか? Java キーワードと同じように @volatile を使用する必要がありますか?

4

2 に答える 2

1

はい、Java と同じように見えます。

テストがハングアップしたり、実行に時間がかかりすぎたりする可能性があるテスト リグの場合、(何らかの理由で) テストに失敗するという約束を使用します。たとえば、タイムアウト モニターはテスト ランナーを「キャンセル」して (スレッドを中断し、compareAndSet フラグを設定して)、promise を失敗して完了することができます。または、テスト準備が不適切に構成されたテストを早期に失敗させる可能性があります。または、テストが実行され、結果が生成されます。より高いレベルでは、テスト装置は未来とその価値を見ているだけです。

Java と異なるのは、先物を構成するためのオプションです。

val all = Future.traverse(tests)(test => {
  val toKeep = promise[Result]    // promise to keep, or fail by monitor
  val f = for (w <- feed(prepare(test, toKeep))) yield {
    monitored(w, toKeep) {
      listener.start(w)
      w.runTest()
    }
  }
  f completing consume _
  // strip context
  val g = f map (r => r.copy(context = null))
  (toKeep completeWith g).future
})
于 2012-09-06T09:13:07.523 に答える
1

自分の問題に対するより良い解決策を見つけたと思います。揮発性変数を使用して操作が終了するタイミングを知らせる代わりに、より優先度の高い終了メッセージをアクターに送信できます。次のようになります。

val a = new Actor() { 
  def act():Unit = {
    loop{ react {
      case "Exit" => exit(); return;
      case MyMessage => {
        //this check makes "Exit" a high priority message, if "Exit" 
        //is on the queue, it will be handled before proceeding to 
        //handle the real message.
        receiveWithin(0) {
          case "Exit" => exit(); return
          case TIMEOUT => //don't do anything.
        }
        sender ! "hi!" //reply to sender
      }
    }}
  }
}

a.start()
val f = a !! MyMessage
while( ! f.isSet && a.getState != Actor.State.Terminated ) {
  //will probably return almost immediately unless the Actor was terminated
  //after I checked.
  Futures.awaitAll(100,f)
}
if( a.getState != Actor.State.Terminated ) {
  f() // the future should evaluate to "hi!"
}
a ! "Exit" //stops the actor from processing anymore messages.
           //regardless of if any are still on the queue.
a.getState // terminated

おそらくこれを書くためのよりクリーンな方法があります..しかし、それは私がアプリケーションで行ったこととほぼ同じです。

キューに「Exit」メッセージがない限り、reactWithin(0) は即時の no-op です。キューに入れられた「Exit」メッセージは、スレッド化された Java アプリケーションに入れる揮発性ブール値を置き換えます。

于 2012-09-10T04:13:17.967 に答える