まだ公式リリースには達していませんcore.async
が、あなたの問題やその他の非同期の問題を非常にきれいに解決する興味深い方法のようです。
のライニンゲンの呪文core.async
は(現在)次のとおりです。
[org.clojure/core.async "0.1.0-SNAPSHOT"]
そして、ここにいくつかの時間のかかる関数を取り、そのうちの 1 つが戻るまでブロックする関数を作成するコードがあります。
(require '[clojure.core.async :refer [>!! chan alts!! thread]]))
(defn return-first [& ops]
(let [v (map vector ops (repeatedly chan))]
(doseq [[op c] v]
(thread (>!! c (op))))
(let [[value channel] (alts!! (map second v))]
value)))
;; Make sure the function returns what we expect with a simple Thread/sleep
(assert (= (return-first (fn [] (Thread/sleep 3000) 3000)
(fn [] (Thread/sleep 2000) 2000)
(fn [] (Thread/sleep 5000) 5000))
2000))
上記のサンプルでは:
chan
非同期チャネルを作成します
>!!
チャネルに値を設定します
thread
本体を別のスレッドで実行する
alts!!
チャンネルのベクトルを取り、それらのいずれかに値が現れると戻ります
これ以上のことがあり、私はまだ頭を悩ませていますが、ここにウォークスルーがあります: https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj
また、David Nolen のブログには、気が遠くなるほど素晴らしい投稿がいくつかあります ( http://swannodette.github.io/ ) 。
編集
Michał Marczyk が非常によく似た質問に答えているのを見たところですが、こちらの方が優れており、キャンセル/短絡が可能です。
Clojure を使用して長時間実行されるプロセスをスレッド化し、それらのリターンを比較する