mik*_*era 4 java concurrency state clojure data-structures
我正在研究Swing + Clojure中的GUI应用程序,它需要各种可变数据(例如滚动位置,用户数据,文件名,选定的工具选项等).
我至少可以看到处理这组数据的三种不同方法:
创建一个ref到所有数据的地图:
(def data (ref {
:filename "filename.xml"
:scroll [0 0] }))
Run Code Online (Sandbox Code Playgroud)
创建各个数据元素的引用映射:
(def datamap {
:filename (ref "filename.xml")
:scroll (ref [0 0]) }))
Run Code Online (Sandbox Code Playgroud)
为命名空间中的每个创建一个单独的ref:
(def scroll (ref [0 0]))
(def filename (ref "filename.xml"))
Run Code Online (Sandbox Code Playgroud)
注意:此数据将同时访问,例如通过后台处理线程或Swing事件处理线程.但是,可能不需要对多个元素进行一致的事务更新.
你推荐的方法是什么?为什么?
首先,如果你最终只使用一个可变状态或几个独立的部分(独立,如"无论是否与另一个一致都没有意义"),为什么不使用Atoms而不是Refs?这是一个非常显着的开销减少,如果你做了很多更新,这实际上很重要.
其次,只要你仔细设计你的交易(即需要提及所有相关的参考,有些可能需要ensure等等),存储文件名,滚动位置等在单独的参考(但不是原子)是正常的- 基本上是交易如果出现不一致的状态,必须确保失败).如果您正在管理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)
Run Code Online (Sandbox Code Playgroud)
另见get-in&assoc-in.
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |