;银行
(defstruct account-struct :id :owner :balance-ref);帐号维度
(def account-map-ref (ref (sorted-map)));保存所有帐号的集合
;新开一个帐号
;@args: 帐号id
;@return:帐号信息
(defn open-account
"creates a new account, stores it in the account map and returns it"
[owner]
(dosync ; required because a Ref is being changed
(let [account-map @account-map-ref
last-entry (last account-map)
id (if last-entry (inc (key last-entry)) 1);如果最后一个帐号存在则自增 否则为1
account (struct account-struct id owner (ref 0 :validator integer?))];新建一个帐号account-struct 强制ref位数字类型
(alter account-map-ref assoc id account);将新建的account-struct帐号更新到account-map-ref
account);返回这个帐号
)
)
;存钱
;args:帐号信息 金额
;return:nil
(defn deposit [account amount]
(dosync
(Thread/sleep 50) ; simulate a long-running operation
(let [owner (account :owner);帐号
balance-ref (account :balance-ref);金额
type (if (pos? amount) "deposit" "withdraw");大于0 或者小于0
direction (if (pos? amount) "to" "from")
abs-amount (Math/abs amount)]
(if (>= (+ @balance-ref amount) 0) ;余额是否够
(do
(alter balance-ref + amount);修改余额 不能使用commute
(println (str type "ing") abs-amount direction owner));打印信息
(throw (IllegalArgumentException.;余额不足给提示 并事务回滚
(str "insufficient balance for " owner
" to withdraw " abs-amount))
)
)
)
)
)
;取钱
;args:帐号信息 金额
;return:nil
(defn withdraw
"removes money from an account"
[account amount]
(deposit account (- amount))
)
;转账
;args:源帐号 目标帐号 金额
;return:nil
(defn transfer [from-account to-account amount]
(dosync
(println "transferring" amount
"from" (from-account :owner)
"to" (to-account :owner))
(withdraw from-account amount)
(deposit to-account amount)))
;查询单个帐号 私有函数
;args:帐号
;return:nil
(defn- report-pri-1
"prints information about a single account"
[account]
(let [balance-ref (account :balance-ref)]
(println "balance for" (account :owner) "is" @balance-ref)))
;查询多个帐号 私有函数
;args:帐号列表
;return:nil
(defn report
"prints information about any number of accounts"
[accounts]
(dosync (doseq [account accounts] (report-pri-1 account))))
;处理当前线程未被处理的异常
;args: 当前线程 异常
;return: nil
(Thread/setDefaultUncaughtExceptionHandler
(proxy [Thread$UncaughtExceptionHandler] []
(uncaughtException [thread throwable]
; Just print the message in the exception.
(println (.. throwable .getCause .getMessage) "线程异常"))))
;调用
(let [mark (open-account "Mark")
tami (open-account "Tami")
thread (Thread. #(transfer mark tami 50))]
(try
(deposit mark 100);存100
(deposit tami 200);存200
(.start thread);转账50
(.join thread) ;等待子线程退出
;(withdraw mark 75);取75
(report [mark tami]);查询
(catch IllegalArgumentException e
(println (.getMessage e) "in main thread"))
)
)