参考映射与地图到refs与多个refs

时间:2010-06-16 20:11:12

标签: java data-structures concurrency clojure state

我正在使用Swing + Clojure中的GUI应用程序,该应用程序需要各种可变数据(例如滚动位置,用户数据,文件名,所选工具选项等)。

我至少可以看到处理这组数据的三种不同方式:

为所有数据的地图创建一个参考:

(def data (ref {
  :filename    "filename.xml" 
  :scroll      [0 0] }))

创建各个数据元素的引用映射:

(def datamap {
  :filename    (ref "filename.xml") 
  :scroll      (ref [0 0]) }))

为命名空间中的每个创建一个单独的引用:

(def scroll (ref [0 0]))    

(def filename (ref "filename.xml"))

注意:将同时访问此数据,例如:通过后台处理线程或Swing事件处理线程。但是,可能不需要对多个元素进行一致的事务更新。

您的推荐方法是什么?为什么?

2 个答案:

答案 0 :(得分:6)

首先,如果你最终只使用一个可变状态或几个独立的部分(独立,如“无论是否与另一个一致都没有意义”),为什么不使用Atoms而不是Refs?这是一个非常显着的开销减少,如果你做了很多更新,这实际上很重要。

其次,只要您仔细设计交易(即需要提及所有相关参考,有些可能需要ensure),在单独的参考(但不是原子)中存储文件名,滚动位置等都可以。 d等 - 如果出现不一致的状态,基本上必须确保交易失败。如果您正在管理GUI状态,那么仔细设计这样的事务可能会浪费精力,其中大多数情况几乎没有变化(除了滚动位置和缓冲区内容,实际上可能经常发生变化的情况? - 我的意思是需要认真考虑的事情,因为答案应该决定最终的设计)。有许多场景,多个引用类型对象比一个更好,我只是不确定管理基本GUI状态是其中之一。 : - )

请注意,在Clojure中对引用类型对象中保存的嵌套结构执行更新非常简洁,例如: (使用Atom):

;; assuming that state-o-matic is an Atom which holds a map,
;; which holds the key of :foo, with which a vector is associated,
;; whose first item is another vector, whose first item is a map
;; which holds the key of :bar associated to a number,
;; the following increments said number
(swap! state-o-matic update-in [:foo 0 1 :bar] inc)

另见get-in& assoc-in

答案 1 :(得分:1)

如果没有并发性 - 那就没有区别,你知道。

但如果它可以在不同的线程中使用,那么第一种情况会更好。因为它保证了你一贯的状态。