19

Clojure で定期的に関数を呼び出す非常に簡単な方法を探しています。

JavaScriptsetIntervalには、私が望む種類の API があります。Clojure で再考すると、次のようになります。

(def job (set-interval my-callback 1000))

; some time later...

(clear-interval job)

私の目的では、これが新しいスレッドを作成するか、スレッドプールで実行するか、その他の何かで実行するかどうかは気にしません。タイミングが正確であることも重要ではありません。実際、指定された期間 (ミリ秒単位) は、1 つの呼び出しが完了してから次の呼び出しが開始されるまでの遅延にすぎません。

4

7 に答える 7

23

Clojure 用のスケジューリング ライブラリも多数あります: (単純なものから非常に高度なものまで)

at-at の github ホームページの例からそのまま:

(use 'overtone.at-at)
(def my-pool (mk-pool))
(let [schedule (every 1000 #(println "I am cool!") my-pool)]
  (do stuff while schedule runs)
  (stop schedule))

(every 1000 #(println "I am cool!") my-pool :fixed-delay true)2 つの開始の間ではなく、タスクの終了と次の開始の間に 1 秒の遅延が必要な場合に使用します。

于 2014-01-28T12:32:13.690 に答える
11

これは、停止チャネルを使用して core.async バージョンを実行する方法です。

(defn set-interval
  [f time-in-ms]
  (let [stop (chan)]
    (go-loop []
      (alt!
        (timeout time-in-ms) (do (<! (thread (f)))
                                 (recur))
        stop :stop))
    stop))

そして使い方

(def job (set-interval #(println "Howdy") 2000))
; Howdy
; Howdy
(close! job)
于 2015-02-06T16:31:30.647 に答える
8

別のオプションは、java.util.Timer のscheduleAtFixedRate メソッドを使用することです。

edit - 単一のタイマーでタスクを多重化し、タイマー全体ではなく単一のタスクを停止します

(defn ->timer [] (java.util.Timer.))

(defn fixed-rate 
  ([f per] (fixed-rate f (->timer) 0 per))
  ([f timer per] (fixed-rate f timer 0 per))
  ([f timer dlay per] 
    (let [tt (proxy [java.util.TimerTask] [] (run [] (f)))]
      (.scheduleAtFixedRate timer tt dlay per)
      #(.cancel tt))))

;; Example
(let [t    (->timer)
      job1 (fixed-rate #(println "A") t 1000)
      job2 (fixed-rate #(println "B") t 2000)
      job3 (fixed-rate #(println "C") t 3000)]
  (Thread/sleep 10000)
  (job3) ;; stop printing C
  (Thread/sleep 10000)
  (job2) ;; stop printing B
  (Thread/sleep 10000)
  (job1))
于 2014-01-28T12:31:53.533 に答える
4

core.async の使用

(ns your-namespace
 (:require [clojure.core.async :as async :refer [<! timeout chan go]])
 )

(def milisecs-to-wait 1000)
(defn what-you-want-to-do []
  (println "working"))

(def the-condition (atom true))

(defn evaluate-condition []
  @the-condition)

(defn stop-periodic-function []
  (reset! the-condition false )
  )

(go
 (while (evaluate-condition)
   (<! (timeout milisecs-to-wait))
   (what-you-want-to-do)))
于 2014-01-28T11:59:11.020 に答える