2015-10-11 21 views
8

scalaz.concurrent.Taskで私の非同期処理を実装したいと思います。私は次のように動作新しいタスクを返すように機能(Task[A], Task[B]) => Task[(A, B)]を必要とする:並列に別のタスクが失敗した場合にタスクをキャンセルする2つの並列タスクを作成するにはどうすればよいですか?

  • 実行Task[A]Task[B]と結果を待ちます。
  • タスクの1つが失敗した場合はをキャンセルして終了するまで待ちます。
  • 両方のタスクの結果を返します。

どのようにこのような機能を実装しますか?

+0

ここでは_cancel_という意味のものがいくつかあります。計算が失敗するだけですか?そして、非決定論の上に 'both'のようなものが働きます。サイクルを無駄にしないようにしたい場合(またはまだ実行中の計算の効果を取り消したい場合)、より複雑になります。 –

+0

はい、今は計算を高速で失敗させたいだけです。 – Michael

答えて

3

前述のとおり、 Nondeterminismを使用してください。たとえば、次のようにwaitALongTimeの最初の副作用が起こるだろう除き、すべての場合には

pairFailSlow(divByZero, waitALongTime).run // fails immediately 
pairFailSlow(waitALongTime, divByZero).run // hangs while sleeping 
pairFailFast(divByZero, waitALongTime).run // fails immediately 
pairFailFast(waitALongTime, divByZero).run // fails immediately 

import scalaz._, scalaz.Scalaz._, scalaz.concurrent._ 

def pairFailSlow[A, B](a: Task[A], b: Task[B]): Task[(A, B)] = a.tuple(b) 

def pairFailFast[A, B](a: Task[A], b: Task[B]): Task[(A, B)] = 
    Nondeterminism[Task].both(a, b) 

val divByZero: Task[Int] = Task(1/0) 
val waitALongTime: Task[String] = Task { 
    Thread.sleep(10000) 
    println("foo") 
    "foo" 
} 

そして。その計算を停止したい場合は、TaskrunAsyncInterruptiblyのようなものを使用する必要があります。

2

Java開発者の間では、並行タスクをキャンセルしないでください。彼らはThread.stop()を粉砕し、非難する。 Thread.stop()がなければ、あなたは本当に未来をキャンセルすることができませんでした。あなたができることは、未来へのシグナルを送ること、あるいは共有変数を変更して、将来コードを定期的にチェックすることです。したがって、先物を提供するすべての図書館は、将来を取り消す唯一の方法を示唆することができます。

私は現在同じ問題に直面しており、キャンセルできる可能性のある先物について自分のライブラリを作成中です。いくつかの困難がありますが、解決される可能性があります。 Thread.stop()を任意の位置で呼び出すことができませんでした。スレッドは共有変数の更新を実行することがあります。ロックは正常に呼び出されますが、アップデートは途中で停止することがあります。二重値の半分しか更新しないなどです。だから私はいくつかのロックを導入しています。スレッドが保護された状態にある場合、スレッドはThread.stop()によって殺されるはずですが、特定のメッセージを送信する必要があります。ガードされた状態は、常に非常に早く待つと考えられます。それ以外の時間は、計算の途中で、スレッドを安全に停止して新しいスレッドに置き換えることができます。

それで、あなたは先物を取り消すことを望んではいけません。さもなければ、あなたは異端であり、Javaコミュニティの誰もあなたに喜んで手を貸しません。スレッドを殺す可能性のある独自の実行コンテキストを定義し、このコンテキストで実行する独自の先物ライブラリを作成する必要があります。

+0

非協調的なスレッドキャンセルでいい言語/環境はありますか?クイック検索では、C#(http://stackoverflow.com/questions/14131608/how-to-terminate-a-thread-in-c)、C++ 11(http://stackoverflow.com/questions/ 12207684/how-do-i-terminate-a-thread-in-c11)またはPython(http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-threadin -python)はそうではありません。 – thoredge

+0

通常のcまたはC++。もちろん、ポインタのように移植可能な方法ではできませんでしたが、すべてのOSには独自のスレッドAPIコールがあり、cまたはC++アプリケーションで使用できます。 c/C++コードでは移植性がありません。 – ayvango

関連する問題