以定时间隔或达到特定大小时处理集合

时间:2013-11-12 04:29:50

标签: clojure

我正在使用

从标准输入中读取字符串
(line-seq (java.io.BufferedReader. *in*))

我怎么能:

  1. 将行存储在集合中
  2. 在某个时间间隔(比如5分钟)处理集合并
  3. 无论时间长短,只要其大小增加到n(比如10),就立即处理它?<​​/ li>

3 个答案:

答案 0 :(得分:1)

我告诉你我的目的:

  1. 正如您可以检查http://clojuredocs.org/clojure_core/clojure.core/line-seq (line-seq (BufferedReader. xxx))的结果是一个序列,所以此函数存储结果(返回一个新的)集合
  2. 您可以使用clojure / core.async超时函数http://clojure.github.io/core.async/#clojure.core.async/timeout来执行此操作,您可以查看https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj以熟悉该库
  3. 只需使用条件(if,when ...)来检查集合的计数

答案 1 :(得分:1)

正如@tangrammer所说,核心异步将是一个很好的方法,或Lamina(每个样本)

答案 2 :(得分:0)

我用一个原子拼凑了一些东西。您可能需要根据需要进行调整(例如,并行执行,不使用future来创建定期处理线程,返回值,......)。下面的代码创建了processor-with-interval-and-threshold,这是一个创建另一个函数的函数,可以给出一系列元素,这些元素按照你描述的方式处理。

(defn- periodically!
  [interval f]
  (future
    (while true
      (Thread/sleep interval)
      (f))))

(defn- build-head-and-tail
  [{:keys [head tail]} n elements]
  (let [[a b] (->> (concat tail elements)
                   (split-at n))]
    {:head (concat head a) :tail b}))

(defn- build-ready-elements
  [{:keys [head tail]}]
  {:ready (concat head tail)})

(defn processor-with-interval-and-threshold
  [interval threshold f]
  (let [q (atom {})]
    (letfn [(process-elements! []
              (let [{:keys [ready]} (swap! q build-ready-elements)]
                (when-not (empty? ready)
                  (f ready))))]
      (periodically! interval process-elements!)
      (fn [sq]
        (let [{:keys [head]} (swap! q build-head-and-tail threshold sq)]
          (when (>= (count head) threshold)
            (process-elements!)))))))

原子q管理三个元素的地图:

  • :head:首先填充并按阈值检查的seq
  • :tail:seq,其元素超出阈值(可能是懒惰的),
  • :ready:要处理的元素。

现在,您可以执行以下操作:

(let [add! (processor-with-interval-and-threshold 300000 10 your-fn)]
  (doseq [x (line-seq (java.io.BufferedReader. *in*))]
    (add! [x])))          

这应该足以让你开始,我想。