6

シナリオ: サーバーが 6 つのアクティブな TCP/IP 接続をリッスンしています。「準備完了」メッセージが届くと、独自のスレッドでイベントが発生します。サーバーは、各接続から「準備完了」メッセージを受信したら、「開始」機能を実行する必要があります。

私のオブジェクト指向ソリューションには、ミューテックスとカウンターの使用が含まれる可能性があります。何かのようなもの:

int _countDown= 6;
object _lock;
void ReadyMessageReceivedForTheFirstTimeFromAConnection() {
    lock(_lock) {
      --_countDown; // 
       if (_countDown==0) Start();
    }
}

ロック/ミューテックスに頼らずに、Clojure でこの問題を解決するにはどうすればよいでしょうか?

4

3 に答える 3

6

この目的のために、CountDownLatch または Phaser を使用できます。

私の先物ライブラリでは、差し迫った、両方を使用しました。最初にCountDownLatchを使用してから、ForkJoin との互換性のためにPhaserに置き換えました (この場合は必要ないかもしれません)。この diffで変更を確認できます。うまくいけば、両方の使用方法のアイデアが得られます。

ラッチの場合、一般的な考え方は次のようになります。

(let [latch (CountDownLatch. 6)]
  (on-receive-message this (fn [_] (.countDown latch)))
  (.await latch)

……とか、そんなこと。

于 2016-02-11T23:24:33.483 に答える
2

これまで言及されていないため、core.asyncを使用して簡単に行うことができます。このMCVEを見てください:

(let [conn-count 6
      ready-chan (chan)]

  ;; Spawn a thread for each connection.
  (doseq [conn-id (range conn-count)]
    (thread
      (Thread/sleep (rand-int 2000))
      (>!! ready-chan conn-id)))

  ;; Block until all connections are established.
  (doseq [total (range 1 (inc conn-count))]
    (println (<!! ready-chan) "connected," total "overall"))

  ;; Invoke start afterwards.
  (println "start"))
;; 5 connected, 1 overall
;; 3 connected, 2 overall
;; 4 connected, 3 overall
;; 0 connected, 4 overall
;; 1 connected, 5 overall
;; 2 connected, 6 overall
;; start
;;=> nil

チャネルを使用してカウントダウン ラッチを実装することもできます ( Christophe Grandから借用)。

(defn count-down-latch-chan [n]
  (chan 1 (comp (drop (dec n)) (take 1))))

core.async の簡単な紹介については、この Gistを確認してください。より長いものについては、「Clojure for the Brave and True」の対応する章をお読みください。

于 2017-01-10T09:57:22.657 に答える