3

Clojure の並行性について学んでいます。

http://dev.clojure.org/display/design/Scheduled+Eventsで、(Stuart Serra による?) 次のような主張に出くわしました。

  • Clojure 関数は、ブロックまたは Java 相互運用なしでは制御フローに時間を使用できません
  • Java 相互運用機能 (ScheduledThreadPoolExecutor) がスレッド ローカル バインディングを認識しない

私はこれらの主張を理解していません。おそらく例を挙げて、明確化をお願いします。具体的には:

  • ScheduledThreadPoolExecutor の何が問題になっていますか? 私は新しい (緑の) スレッドを開始しているので、スレッドごとのバインディングが引き継がれるとは思っていません。
  • 私は通常の Clojure 関数をスケジュールすることができます。

どうもありがとう!

4

1 に答える 1

4

わかりました、私はそれを手に入れたと思います。

これを試したとします:

(def pool (atom nil))

(defn- thread-pool []
    (or @pool
        (reset! pool (ScheduledThreadPoolExecutor. 1))))

(def ^:dynamic *t* 0)

(binding [*t* 1]
    (future (println "first example:" *t*)))

(binding [*t* 1]
    (.schedule (thread-pool) (fn [] (println "second example:" *t*)) 0 
               TimeUnit/SECONDS))

(binding [*t* 1]
    (.schedule (thread-pool) (bound-fn [] (println "third example:" *t*)) 0
               TimeUnit/SECONDS))

出力は次のようになります。

first example: 1
second example: 0
third example: 1

最初のケースでは、future マクロはプライベート関数 binding-conveyor-fn で本体をラップします。これにより、呼び出しスレッドのバインディング フレームがレキシカル スコープに保存され、ラップされた関数を呼び出す前に復元されます。

3 番目のケースでは、bound-fn は呼び出しスレッドのバインディングをフレームにプッシュし、関数本体を実行して、バインディングをポップします。

2 番目のケースでは、誰もスレッドごとのバインドを保存しません。Java クラスは確実にそれを認識していないため、t Var のルート値にドロップします。

誰かがこれを面白いと思うことを願っています。

于 2012-08-17T15:01:33.030 に答える