Java clojure银行账户转账示例
我不熟悉Java clojure银行账户转账示例,java,clojure,stm,Java,Clojure,Stm,我不熟悉clojure,我正在尝试实现经典的并发示例aka银行账户转账。我想使用事务内存实现它 下面是java static class Account { private double balance; public synchronized void withdraw(double value) { balance -= value; } public synchronized void deposit(double value) {
clojure
,我正在尝试实现经典的并发示例aka银行账户转账
。我想使用事务内存实现它
下面是java
static class Account {
private double balance;
public synchronized void withdraw(double value) {
balance -= value;
}
public synchronized void deposit(double value) {
balance += value;
}
}
static synchronized void transfer(Account from, Account to, double amount) {
from.withdraw(amount);
to.deposit(amount);
}
在我看来,我不确定实现是否正确,但它似乎是有效的
这是我在clojure
(deftype Account [balance])
(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))
(defn print-accs []
(println " account 1 => " (deref (.balance account1))
" account 2 => " (deref (.balance account2))))
(defn transfer [from to amount]
(dosync
(alter (.balance from) - amount)
(alter (.balance to) + amount)))
(print-accs) ; 100 100
(transfer account1 account2 10)
(print-accs) ; 90 110
使用事务性内存
或正确执行银行账户转账
是否是一个恰当的例子?我是否对字段使用了ref
正确,还是应该对整个帐户
实例使用它?您不需要deftype
,但在其他方面它看起来不错。我会简化一点如下:
(def account1 (ref 100))
(def account2 (ref 100))
(defn print-accs []
(println " account 1 => " @account1
" account 2 => " @account2 ))
(defn transfer [from to amount]
(dosync
(alter account1 - amount)
(alter account2 + amount)))
(print-accs) ; 100 100
(transfer account1 account2 10)
(print-accs) ; 90 110
我推荐的一件事是始终打开浏览器选项卡。这些链接可以在ClojureDocs.org上找到更详细的信息。享受吧
更新
对于帐户余额这样的单个值,将余额包装到帐户
记录中没有多大意义。如果要创建一组具有相同字段的记录,可能需要defrecord
:
(defrecord Account [name balance])
大多数应用程序一开始都使用普通的地图,比如
(def joe-acct (ref {:name "Joe" :balance 100.00})
因为它简单灵活。稍后,如果要为始终由名称和余额组成的映射指定typename,可以切换到
(defrecord Account [name balance])
(def joe-acct (ref (Account. "Joe" 100.00)))
deftype
被认为是“较低级别”,现在很少使用。见:
您不需要
deftype
,但在其他方面它看起来不错。我会简化一点如下:
(def account1 (ref 100))
(def account2 (ref 100))
(defn print-accs []
(println " account 1 => " @account1
" account 2 => " @account2 ))
(defn transfer [from to amount]
(dosync
(alter account1 - amount)
(alter account2 + amount)))
(print-accs) ; 100 100
(transfer account1 account2 10)
(print-accs) ; 90 110
我推荐的一件事是始终打开浏览器选项卡。这些链接可以在ClojureDocs.org上找到更详细的信息。享受吧
更新
对于帐户余额这样的单个值,将余额包装到帐户
记录中没有多大意义。如果要创建一组具有相同字段的记录,可能需要defrecord
:
(defrecord Account [name balance])
大多数应用程序一开始都使用普通的地图,比如
(def joe-acct (ref {:name "Joe" :balance 100.00})
因为它简单灵活。稍后,如果要为始终由名称和余额组成的映射指定typename,可以切换到
(defrecord Account [name balance])
(def joe-acct (ref (Account. "Joe" 100.00)))
deftype
被认为是“较低级别”,现在很少使用。见:
我使用了deftype
,因为我想模拟为帐户创建一个特定的类。这就是为什么我问这样一个问题:我是否应该为帐户余额字段的Ref
实例存储Ref
,因为我不确定。顺便问一下,您是否碰巧知道Ref
何时从内存中删除?被GC引用?引用和其他任何对象一样是一个“对象”,当不再被引用时,它会被GC删除。对于Account实例,ref
?我为值设置了ref
-如果我像这样将Account
包装到ref
(def-ref-acc(ref(Account.100)))
,会有区别吗?但是如果我有多个字段,我应该使用什么方法?整个类还是仅仅字段?好吧,我使用了deftype
,因为我想模拟为Account
创建一个特定的类。这就是为什么我问这样一个问题:我是否应该为帐户余额字段的Ref
实例存储Ref
,因为我不确定。顺便问一下,您是否碰巧知道Ref
何时从内存中删除?被GC引用?引用和其他任何对象一样是一个“对象”,当不再被引用时,它会被GC删除。对于Account实例,ref
?我为值设置了ref
-如果我像这样将Account
包装到ref
(def-ref-acc(ref(Account.100)))
,会有区别吗?但是如果我有多个字段,我应该使用什么方法?整个类还是仅字段?键入传输
?您将从传递到
,但稍后将使用帐户[12]
哦。是否在传输中固定了typo
?您将从传递到
,但稍后将使用帐户[12]
哦。固定的