2015-01-05 65 views
1

例如在一個網絡爬蟲中,它維護着一組全球訪問的URL。一旦工作人員開始使用URL或已完成URL,其他工作人員就不應該使用相同的URL。在Java中實現這一點的一種方式是將訪問的URL放入ConcurrentHashMap(Set可能更好)。每個工人看地圖訪問一個網址原子在網絡爬蟲中的習慣用法

if (visited.putIfAbsent(url, true) == null) { 
    crawl(url); 
} else { 
    // do nothing 
} 

在Clojure中之前,我用在​​一組。每當我要使用最新訪問的URL交換一個新集時,交換功能應檢查該集是否已有此URL。如果URL存在,工作人員應該從那裏停下來。爲了能夠告訴工人,如果交換成功,我必須在全局狀態保存返回值一樣[visited-urls last-swap-succeeded]

(def state (atom [#{} nil])) 
(defn f [state key] (let [[visited-urls l] state] (if (visited-urls key) [visited-urls false] [(conj (visited-urls key) true])))) 

工人應該做的

(when (second (swap! state f url)) (crawl url)) 

它的工作原理,但看起來很醜陋我。問題是交換功能不允許返回值到callsite。在Clojure中有更好的方法嗎?

回答

5

Refs有點爲這種事情。這裏有一個簡單的方法來做到這一點

(when (dosync (when-not (@visited-urls-ref url-to-visit) 
       (alter visited-urls-ref conj url-to-visit))) 
    ; continue crawling url-to-visit 
) 

我無法想象它會爲網絡爬蟲添加任何重大開銷。

就個人而言,假設訪問網址的順序並不重要,我會創建一個帶有dedupe傳感器的core.async頻道,並且只需讓所有工作人員將/從中取出網址即可。

+0

這是什麼參考在哪裏做:-) –