日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
Kestrel.scala中的QueueCollection

有關Kestrel的Scala實例已經介紹到了第三篇,接下來介紹Scala中的一個走讀分支:QueueCollection。

創(chuàng)新互聯(lián)專注于北海企業(yè)網站建設,響應式網站開發(fā),商城系統(tǒng)網站開發(fā)。北海網站建設公司,為北海等地區(qū)提供建站服務。全流程按需搭建網站,專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務

在Kestrel.scala的startup方法中,告訴我們接下來有兩個走讀的分支,一個是QueueCollection和PersistentQueue。另一個是KestrelHandle。KestrelHandle是和NioSocketAcceptor相聯(lián)系的,所以可以想想KetrelHandle是用來處理鏈接……與之相關的還有memcache目錄下的Codec.scala。

我們先忽略Kestrel.scala在startup中的幾個語法細節(jié),從相對比較簡單的QueueCollection開始吧:

 
 
 
  1. class QueueCollection(queueFolder: String, private var queueConfigs: ConfigMap) {
  2.   ……
  3.   if (! path.isDirectory) {
  4.     path.mkdirs()
  5.   }
  6.   ……
  7. }

這是一個Scala的比較特殊語法。class本身就是一個建構函數。程序中queueFolder和queueConfigs是創(chuàng)建是必須的兩個參數。class在Scala里面就支持一種建構函數。這里的參數也可以看做是整個class的變量,所以程序中的private只表示在類以外的地方,沒有辦法獲取queueConfigs這個參數。

接下來是關于HashMap的創(chuàng)建:

 
 
 
  1. private val queues = new mutable.HashMap[String, PersistentQueue]

我們知道HashMap是有兩個類型,一個是鍵的類型,一個是值的類型。在queues里面,String就是鍵,PersistentQueue就是值。這跟Java/C++的模板累死,不需要特別的解釋了。

然后是一個很多地方都用到的Count,在Count.scala里面有說明,就是一個統(tǒng)計技術的類,寫法很干凈,注意里面的函數定義,都沒有用大括號。多看幾遍就熟悉,Scala是怎么定義函數的了。顯然,這看起來更像是命令,而不是函數體的聲明。

經過兩段比較好理解的代碼之后,出現了一段恐怖的代碼:

 
 
 
  1. queueConfigs.subscribe { c =>
  2.   synchronized {
  3.     queueConfigs = c.getOrElse(new Config)
  4.   }
  5. }

如果只是看這段代碼,就有種喉嚨被卡住,咽不下去又吐不出來的感覺。這段代碼做了些什么,大家都能猜出來,郁悶的是,這到底遵循的是那個語法規(guī)范呢?咋代碼就寫得那么四不像呢?不過如果我們回過來看一下net.lag.configgy.configMap中subscribe的定義,似乎就能明白多一點:

 
 
 
  1. def subscribe(f: (Option[ConfigMap]) => Unit): SubscriptionKey = {
  2.   subscribe(new Subscriber {
  3.     def validate(current: Option[ConfigMap], replacement: Option[ConfigMap]): Unit = { }
  4.     def commit(current: Option[ConfigMap], replacement: Option[ConfigMap]): Unit = {
  5.       f(replacement)
  6.     }
  7.   })
  8. }

看來還是有點難度——呃,其實這是Kestrel的一個非常靈活的功能,定義作為參數的函數的類型:

 
 
 
  1. func_name : (param_type1, param_type2) => Unit

func_name是一個有兩個參數的函數,參數類型分別是param_type1和param_type2。所以subscribe的參數是一個有一個參數的函數,這個參數所以Option[ConfigMap]。關于Option, Some的話題,我們稍后再談。這已經不影響程序的閱讀了。

回到在QueueCollection.scala的代碼,當我們知道subscribe的參數是一個函數的時候,下面這段代碼的作用就是,當queueConfigs的某些狀態(tài)變化的時候,會調用一個叫commit的內部函數,而這個內部函數的功能,就是把新替換的配置,作為參數c,傳遞給這段代碼,結果是queueConfigs = c.getOrElse(new Config)。涵義是,如果不存在就添一個缺省值。

 
 
 
  1. queueConfigs.subscribe { c =>
  2.   synchronized {
  3.     queueConfigs = c.getOrElse(new Config)
  4.   }
  5. }

繞了一圈,其實是定義了一個觸發(fā)器,并且觸發(fā)器的作用是,當設置是空置的時候,補上一個標準的缺省值。完全是殺雞用了牛刀。但是回過來我們重新考慮Scala對架構上的意義,這種把函數作為參數的做法,可以很方便的實現callback操作,當然這需要配合上object這樣的類,否則尋找對應的callback類,還需要費點周章。

隨后,我們看到了著名的閉包(closure),而且一來還來了兩段,第一段是filter,對于所有的成員“name”,如果 => 后面的內容返回是成功的話(如果name不包含~~),就添加到list里面去。

 
 
 
  1. def loadQueues() {
  2.   path.list() filter { name => !(name contains "~~") } map { queue(_) }
  3. }

第二段是把list變成一個map,完整的寫法應該是

 
 
 
  1. map { _ => queue(_) }

很多時候不需要寫成那么麻煩,可以直接把 _ => 給省略了。有時候因為習慣的原因,你會猜想queue又是一個什么特殊的語法?其實它一點都不特殊,往下大概10行左右,就是它的定義。queue,是把一個字符串的隊列名,轉變成一個真正的PersistentQueue的函數。所以load_queues,在大體上起了初始化隊列的作用。

后面的段落中還有一個使用了closure的語法:

 
 
 
  1. def currentItems = queues.values.foldLeft(0L) { _ + _.length }

查詢一下foldLeft的函數說明如下:

 
 
 
  1. def  foldLeft[B](z : B)(op : (B, A) => B) : B

根據函數的定義,foldLeft的函數,就是用迭代的方法,把所有元素的 length,也就是 _.length 累加起來,最后返回。_.length的總數。我們從語法上不難發(fā)現,{_ + _.length} 可以看做是 { a , b => a + b.length }。

讀到這里,暫時告一段落。后半段QueueCollection還有一個重要的Scala語法——case下一次再討論吧。


本文標題:Kestrel.scala中的QueueCollection
文章出自:http://www.dlmjj.cn/article/djiooje.html