2

Executors.newSingleThreadScheduledExecutor() を使用して Clojure 関数をスケジュールしようとしています。厄介なのは、結果の ScheduledFutureTask で .get() を呼び出すと、関数の結果ではなく nil が返されることです。

私はヒッキー氏の先物の実装をモデルとして採用しています。

(ns my.ns
    (:import (java.util.concurrent Executors ThreadFactory TimeUnit)))


(def ^:private thread-pool-scheduler (atom nil))


(def ^:private thread-pool-counter (agent 0))

(defn- get-and-increment-thread-id []
   (-> thread-pool-counter (send inc) deref))

(def ^:private thread-factory 
    (reify ThreadFactory 
     (newThread [this f]
        (let [thread (Thread. f)]
          (.setName thread (format "clojure-scheduled-future-thread-pool-%d"
                       (get-and-increment-thread-id)))
          thread))))

(defn scheduled-future-call [^Callable f ^long delay ^TimeUnit unit]
    (.schedule (scheduled-futures-executor) (bound-fn* f) delay unit))

(defn start-scheduled-futures-executor! []
    (reset! thread-pool-scheduler
    (Executors/newSingleThreadScheduledExecutor thread-factory)))

(defn scheduled-futures-executor []
    (or @thread-pool-scheduler
        (start-scheduled-futures-executor!)))

すべてが機能し、適切な場合に副作用が発生します (例: #(println "ok") のスケジューリング)。ただし、結果の ScheduledFutureTask の get() メソッドを呼び出すと、常に nil が返されます (例: #(+ 5 5) のスケジューリング)。

Callable を明示的に拡張しようとしましたが、bound-fn* を省略しようとしましたが、結果は同じです。

(defprotocol ISchedule
    (schedule [this delay time-unit]))

(extend Callable
    ISchedule
    {:schedule (fn [this delay time-unit]
       (.schedule (scheduled-futures-executor) this delay time-unit))})

私の直感では、ScheduledExecutorService は schedule(Runnable, long, TimeUnit) よりも schedule(Callable, long, TimeUnit) を選択していますが、ヒントを入力して修正しないでください。

助けやヒントをありがとう!

4

2 に答える 2

3

私の直感では、ScheduledExecutorServiceはschedule(Callable、long、TimeUnit)よりもschedule(Runnable、long、TimeUnit)を選択しています。

私はあなたが正しいと思います、私だけが修正Callableしました、そしてそれはきちんと働きました。Callable( importステートメントのクラスのリストにも追加しました)。

編集:私はまたへの呼び出しを削除しましたbound-fn*

見てみな:

(defn make-callable [f] (reify Callable (call [this] (f))))

(def cat (make-callable (fn [] (println "meeow") "i am a cat")))

(def who-are-you? (scheduled-future-call cat 2 TimeUnit/SECONDS))

(println "Tell me who you are!\n\t" (.get who-are-you?))

出力:

meeow
Tell me who you are!
    i am a cat
于 2012-08-20T17:13:05.420 に答える
1

とにかくbound-fnを呼び出すだけで、結果が型ヒントされていないため、^Callableヒントonfは役に立ちません。実際に渡すものをヒントする必要があります.schedule。さらに重要なことに、ターゲット オブジェクト自体 (エグゼキューター) にヒントを与える必要があります。これは、ターゲット オブジェクトがヒントされていない場合、コンパイラは引数のヒントを (かなり合理的に) 無視するためです。ターゲットのタイプ!

したがって、これらの両方を let バインディング1でヒントすれば、問題ないはずです。あいまいさを解消するために、残りのすべての引数もほのめかす必要があるかもしれませんが、私はそうは思いません。

1注:それらを生成する式をほのめかさない^Callable (bound-fn f)でください。これは通常は機能しますが、説明が複雑なシナリオでは機能しない場合があります。そのシナリオを避けるのが最善です。

于 2012-08-20T19:08:39.997 に答える