莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

              有段時間沒更新blog了。主要是這段時間內自己處于一個比較莫名的階段,靜不下心來做事讀書,或者說不知道自己應該做什么。原因有工作上的調動問題,有生活中的一些壓力。最近了換了項目小組,與arbow一起去搞某個產品的分布方案。這個產品已經比較穩定,我過去沒有參與過它的開發工作,沒有經歷過這個開始顯的有點復雜的項目從無到有的過程,因此對代碼、對業務、對組員都顯的比較陌生。
              過往的項目經歷都是在別人給出明確目標下的開發工作,或者說習慣于接受別人安排的任務,有的放矢地去實現一些東西。而現在的處境是到一個不熟悉的項目,去實現一個不大明確的目標,因而我自己有點搞不清楚狀況,再加上生活中那么些壓力,心態也出了問題,很被動地去等待,而非積極地去探討和介入這些工作,簡單點說,有點像局外人的感覺。
              今天跟經理談了下,我覺的自己最近的效率和狀態很差,想請假休息。經理跟我聊了些他的經驗,我才明白自己的問題所在。過于急躁和被動,這不是休息能解決,首要的還是要調整心態,以踏實謙虛的心理去學習新東西,主動去做些事情,這樣才能找回那份工作熱情。
              題外話,廣州真的好熱,我這個福建人都很不習慣。熱還罷了,最主要是比較潮濕和悶氣,這兩天終于下雨了,感覺清爽很多。

          posted @ 2008-08-06 23:02 dennis 閱讀(415) | 評論 (0)編輯 收藏

              Ruby也能寫servlet?是的,沒開玩笑,而且挺方便的,因為Ruby的標準庫就自帶了一個webrick,webrick本身又有一個serlvet容器,隨時隨地啟動一個web server,實在是很方便。
              先看個最簡單的例子,輸出hello到瀏覽器:
          require 'webrick'
          require 
          'net/http'
          include WEBrick

          class HelloServlet < HTTPServlet::AbstractServlet
            
          def hello(resp)
              resp[
          "Content-Type"]="text/html;charset=utf-8"
              resp.body
          ="hello,ruby servlet"
            end
            private :hello
            
          def do_GET(req,resp)
              hello(resp)
            end
            
          def do_POST(req,resp)
              hello(resp)
            end
          end
          if $0==__FILE__
            server
          =HTTPServer.new(:Port=>3000)
            server.mount(
          "/hello",HelloServlet)
            trap(
          "INT"){ server.shutdown }
            server.start
          end
              是不是跟java很像?所有的serlvet都要繼承自HTTPServlet::AbstractServlet,并實現do_GET或者do_POST方法。在這行代碼:
          server=HTTPServer.new(:Port=>3000)

              我們啟動了一個HTTP Server,端口是3000,然后將HelloServlet掛載到/hello這個路徑上,因此,執行這個腳本后,可以通過http://localhost:3000/hello調用HelloServlet,簡單地只是顯示字符串"hello,ruby servlet"。
             
          這個簡單的例子沒有任何交互,并且顯示的html也是寫死在腳本中,顯然更好的方式應該通過模板來提供,可以使用Ruby標準庫的erb模板。再給個有簡單交互的例子,現在要求用戶輸入姓名,然后提交給HelloServlet,顯示"hello,某某某"。嗯,來個最簡單的提交頁面:
          <html>
          <body>
          <center>
             
          <form action="http://localhost:3000/hello" method="post">
               
          <input type="text" name="name" size=10/><br/><br/>
               
          <input type="submit" name="submit" value="submit"/>
             
          </form>
             
          </center>
          </body>
          </html>

              注意到,我們采用POST方法提交。再看看erb模板:
          <html>
              
          <head></head>
              
          <body>
                hello,
          <%=name%>
              
          </body>
          </html>   
              其中的name是我們將要綁定的變量,根據用戶提交的參數。最后,修改下HelloServlet:
          require 'webrick'
          require 
          'net/http'
          include WEBrick

          class HelloServlet < HTTPServlet::AbstractServlet
            
          def do_GET(req,resp)
              do_POST(req,resp)
            end
            
          def do_POST(req,resp)
              name
          =req.query["name"]
              
          #讀取模板文件
              template=IO.read(File.dirname(__FILE__)+"/hello.html")
              message
          =ERB.new(template)
              resp[
          "Content-Type"]="text/html;charset=utf-8"
              resp.body
          =message.result(binding)
            end
          end
          if $0==__FILE__
            server
          =HTTPServer.new(:Port=>3000)
            server.mount(
          "/hello",HelloServlet)
            trap(
          "INT"){ server.shutdown }
            server.start
          end
              與前一個例子相比,不同點有二,一是通過req.query["name"]獲得用戶提交的參數name,二是resp的body是由模板產生,而不是寫死在代碼中。在一些臨時報表、臨時數據的展示上,可以充分利用Ruby的這些標準庫來快速實現。
             

          posted @ 2008-07-23 12:02 dennis 閱讀(2885) | 評論 (0)編輯 收藏

          1、如果用java6的ScriptEngineManager來調用JRuby,并且腳本使用到了Ruby的標準庫(比如我用到了YAML庫),如果沒有正確設置,是會找不到標準庫的。通過打印$:變量可以看到文件的加載路徑,比如在某臺機器上的打印的結果:
             puts $:
             輸出:
          .
          /root/.jruby/lib/ruby/site_ruby/1.8
          /root/.jruby/lib/ruby/site_ruby
          /root/.jruby/lib/ruby/1.8
          /root/.jruby/lib/ruby/1.8/java
          lib/ruby/1.8
          ......略

          顯然,默認會到當前用戶的主目錄下尋找.jruby隱藏目錄,將此目錄作為Ruby的安裝目錄,因此,可以在~user/.jruby放置一個jruby實現,一勞永逸地解決問題,不然就要自己手工添加完整的路徑到$:變量中。

          2、nio的臨時selector的使用,了解grizzly的都知道,Grizzly框架有一個比較與眾不同的地方在于使用臨時selector注冊channel進行讀或者寫。這個帶來什么好處呢?一個是,通常我們可能將read派發到其他線程中去,如果一次沒有讀完,那么就得繼續注冊OP_READ到主selector上;注意,nio在一些平臺上有個問題,就是SelectionKey.interestOps方法跟Selector.select方法會有并發沖突,產生奇怪的現象,因此,你會看到大多數的nio框架都會保證SelectionKey.interestOps跟Selector.select的調用在同一個線程;在沒有讀完繼續注冊這個場景下,免不了線程間的context switch,如果采用一個臨時selector注冊并讀取,就可以避免這個切換開銷。另外,對于write調用,通常你可能這樣寫:
          while (byteBuffer.hasRemaining()) {
            
          int len = socketChannel.write(byteBuffer);
            
          if (len < 0){
             
          throw new EOFException(); 
            }
          }


             在負載比較高的時候,write返回0的次數會越來越多,while循環將空耗多次導致CPU占用偏高,這個問題在win32上比較嚴重,同樣可以采用臨時selector的解決(Cindy2.x是留在隊列,等待下次寫)。下例是采用臨時Selector進行讀的例子:

                          Selector readSelector = SelectorFactory.getSelector();
                          SelectionKey tmpKey 
          = sc.register(readSelector,
                                  SelectionKey.OP_READ);
                          tmpKey.interestOps(tmpKey.interestOps() 
          | SelectionKey.OP_READ);
                          
          int code = readSelector.select(1000);
                          tmpKey.interestOps(tmpKey.interestOps()
                                  
          & (~SelectionKey.OP_READ));
                          
          if (code > 0) {
                              
          do {
                                  n 
          = sc.read(in);
                              } 
          while (n > 0 && in.hasRemaining());
                              in.flip();
                              decode();
                              in.compact();
                          }
                          SelectorFactory.returnSelector(readSelector);
              這樣的方式,某種意義上可以認為是non-blocking模式下的阻塞讀,在網絡條件穩定的情況下(比如內網),能帶來比較高的效率。

          3、spymemcached,是另一個memcached的java client實現,采用nio。最近遇到的問題是它跟原來的MemcachedClient的兼容問題,用它去操作MemcachedClient存儲的數據。spymemcached是通過Transcoder來實現序列化,Transcoder的WhalinTranscoder實現類兼容了Greg Whalin的MemcachedClient:
          private Transcoder whalinTranscoder = new WhalinTranscoder();


          Future
          <Object> f = memcachedClient.asyncGet(id, whalinTranscoder);

             各個方法都有重載的版本用以指定Transcoder。

          posted @ 2008-07-07 20:41 dennis 閱讀(1257) | 評論 (2)編輯 收藏

              http://wuhanpin.blogcn.com/index.shtml,來自一線記者關于XXXX事件的blog,謊話重復千遍也就成了真理,但是歷史終將還原真實。要看的趕緊看哦,過不了幾天恐怕要被河蟹了。

          posted @ 2008-07-03 09:16 dennis 閱讀(561) | 評論 (0)編輯 收藏

              沸沸揚揚的華南虎案(更想說是鬧劇)終于告一段落,在廣大網民的火眼金睛下,假老虎終究沒有變成真老虎,沒有上演指“畫”為“虎”的現代成語故事。盡管處理結果有那么點抓小放大的意思,但還是值的紀念的一個日子。
          更正:我還是太樂觀了,貴州某地發生的事情,讓我無法平靜,我能做些什么?

          posted @ 2008-06-29 16:07 dennis 閱讀(468) | 評論 (0)編輯 收藏

              主動關閉的Socket端會進入TIME_WAIT狀態,并且持續2MSL時間長度,MSL就是maximum segment lifetime(最大分節生命期),這是一個IP數據包能在互聯網上生存的最長時間,超過這個時間將在網絡中消失。MSL在RFC 1122上建議是2分鐘,而源自berkeley的TCP實現傳統上使用30秒,因而,TIME_WAIT狀態一般維持在1-4分鐘。
              TIME_WAIT狀態存在的理由:
          1)可靠地實現TCP全雙工連接的終止
              在進行關閉連接四路握手協議時,最后的ACK是由主動關閉端發出的,如果這個最終的ACK丟失,服務器將重發最終的FIN,因此客戶端必須維護狀態信息允許它重發最終的ACK。如果不維持這個狀態信息,那么客戶端將響應RST分節,服務器將此分節解釋成一個錯誤(在java中會拋出connection reset的SocketException)。因而,要實現TCP全雙工連接的正常終止,必須處理終止序列四個分節中任何一個分節的丟失情況,主動關閉的客戶端必須維持狀態信息進入TIME_WAIT狀態。

          2)允許老的重復分節在網絡中消逝 
              TCP分節可能由于路由器異常而“迷途”,在迷途期間,TCP發送端可能因確認超時而重發這個分節,迷途的分節在路由器修復后也會被送到最終目的地,這個原來的迷途分節就稱為lost duplicate。在關閉一個TCP連接后,馬上又重新建立起一個相同的IP地址和端口之間的TCP連接,后一個連接被稱為前一個連接的化身(incarnation),那么有可能出現這種情況,前一個連接的迷途重復分組在前一個連接終止后出現,從而被誤解成從屬于新的化身。為了避免這個情況,TCP不允許處于TIME_WAIT狀態的連接啟動一個新的化身,因為TIME_WAIT狀態持續2MSL,就可以保證當成功建立一個TCP連接的時候,來自連接先前化身的重復分組已經在網絡中消逝。

          新的SCTP協議通過在消息頭部添加驗證標志避免了TIME_WAIT狀態。

          posted @ 2008-06-23 01:25 dennis 閱讀(17842) | 評論 (3)編輯 收藏

              歐洲杯開賽至今,由于要上班,擔心起不了床,完整的比賽沒看過幾場,錯過好多場精彩對決了,今天晚上熬夜看俄羅斯VS.荷蘭,真值了,阿爾沙文成了俺的新偶像,過人如草芥,太牛X了。這廝在FM2008里就很猛了,我的樸茨茅斯檔第一個買的就是他,第一年就排上了聯賽第三,讓他打前腰,助攻第一,進球全隊第三,性價比超值。


          posted @ 2008-06-22 05:43 dennis 閱讀(514) | 評論 (0)編輯 收藏

              加班在國內的公司好像是司空見慣的事情,更司空見慣的是加班不給加班費。從業三年,加班次數也不少,不過最長的一次是連續加了一個月的班,天天10點多才回家,比起某些同學深更半夜還在加班的差了些。在目前的公司,除了剛開始偶爾加班外,現在我基本就是下班就走人了,還沒有因為我負責的模塊延期導致的項目的延期,相反,自信工作的效率還是比較高的,自然上班時間能搞定的事情,何必拖到下班后?
              不排除有些人喜歡安靜的環境,下班后,人少了,一個人敲代碼感覺更好,效率更高。這其實顛倒了問題的本質,本質是公司沒有為員工創造一個舒適的工作環境,“家具警察”們是絕不樂意給你安排一個私人小空間的。問題是,代碼不是生活的全部,如果天天這樣晚上在公司加班,可以想見這人的生活該如何枯燥,而生活枯燥的人很容易失去想象力和直覺,并且心理上難免會有點毛病。公司不應該鼓勵加班,公司應該鼓勵的是大家在上班期間高效地完成工作,然后盡快回家去“生活”。其實吧,如果我們上班少看點新聞,少開點小差,這個效率絕對是不低的。
              聽聞有領導對我們部門不滿,說我們部門總是下班后人都走光了:)這樣的觀點真是奇怪,難道加班就能顯示這個部門很努力、很負責?況且,我看到很多加班的同學更多是在玩游戲或者干自己的事情,公司領導們難道看不到這一點?或者他們只要看見有人在那,心里就比較舒服點。這其實很奇怪的,我認為經常加班的部門絕對是有問題的,而且很大程度上是項目管理不當引起的。

          posted @ 2008-06-21 12:32 dennis 閱讀(1142) | 評論 (11)編輯 收藏

              SocketChannel和ServerSocketChannel,兩者的父類是SelectableChannel,它在jdk中的文檔有這么段話:

              Once registered with a selector, a channel remains registered until it is deregistered.This involves deallocating whatever resources were allocated to the channel by the selector.
              A channel cannot be deregistered directly; instead, the key representing its registration must be cancelled. Cancelling a key requests that the channel be deregistered during the selector's next selection operation.

              也就是說關閉一個已經注冊的SelectableChannel需要兩個步驟:

          1)取消注冊的key,這個可以通過SelectionKey.cancel方法,也可以通過SelectableChannel.close方法,或者中斷阻塞在該channel上的IO操作的線程來做到。

          2)后續的Selector.selectXXX方法的調用才真正地關閉本地Socket。

              因而,如果,如果在取消SelectionKey后沒有調用到selector的select方法(因為Client一般在取消key后, 我們都會終止調用select的循環,當然,server關閉一個注冊的channel我們是不會終止select循環的),那么本地socket將進入CLOSE-WAIT狀態(等待本地Socket關閉)。簡單的解決辦法是在 SelectableChannel.close方法之后調用Selector.selectNow方法,類似:

             Selector sel;
             SocketChannel sch;
             // …
             sch.close();
             sel.selectNow();


              Nio編程有很多這樣細節性的東西需要注意,通常情況下還是利用成熟的框架為妙。

          posted @ 2008-06-18 01:50 dennis 閱讀(2458) | 評論 (2)編輯 收藏

            JavaOne2008上有個session《Upcoming Java Programming Language Features》,講了即將到來的jdk7可能引入的新的語言特性,比較開眼界的是jsr308對Annotation的擴展使用,更多地作為斷言或者說checker使用以便減少bug。在ppt前面,我覺的更有意思的是對java語言演化的講述,做個筆記。

          1、應用VS.語言

          應用是特性越多越好,應用是rich的;而語言是pure的,更少的、普通的特性更好。

          2、添加一個java語言特性的三個前提:尊重過去、著眼未來以及顧及模型。

          無論是增加、減少或者改變一個feature都可能broken已經存在的代碼,一個新增加的feature必須兼容已經存在的代碼,兼容是個沉重的包袱,就java語言而言,我相當認同尊重過去這一點,哪怕加入閉包這樣的特性也不應當以損壞兼容性為代價,更好的選擇是將這些特性讓jvm上的新語言去實現(比如JRuby、Scala),java語言作為成熟的工業語言本身不應當做太大的改變。而著眼未來,也就是說新的語言特性應該為未來的語法擴展留有空間,它的語法/語義不應當跟現存的或者潛在的特性相沖突,以便可以持續地演化。再談顧及當前的模型,一門語言代表著一種計算模型,比如simulaOO模型(classes)Erlang就是inter-process communication的模型(actor)。Java語言也有一個簡單的模型:首先它是“高層”語言,是一門通用、并發、基于類的OO語言,其次,它跟APIJVM有良好的結合。Java語言模型有四個原則:

          a)鼓勵high-level實踐,通過抽象來隱藏偶然復雜度。簡而言之:do the right thing

          b)追求清晰,程序被讀的時候遠遠多于寫。簡而言之:do the thing right.

          c)青睞靜態類型,靜態類型能增進對代碼的信心,靜態類型能證明bug在編譯時的不存在,而測試和動態類型能證明bug的存在。我的觀點是,大多數難以尋找和解決的bug都是runtime的,靜態類型在此方面能給出的幫助有限,充分并且適宜的測試更加能增強你對應用的信心。

          d)語言比之API的更廣泛。one language,many apiAPI來去匆匆,而語言卻是forever,因而將語言和API分離是明智的,一些特性可以做為庫來實現,jdk5并發庫的引入就很好,jdk7在并發方面同樣將引入fork/join模型。

          java語言的演化也當遵循這四個原則。再看看傳說中的閉包語言,當它跟泛型結合的時候寫出來的東西還談得上清晰嗎?閉包的實現能否解決兼容性問題也是個疑問。就四個提案,C3S需要引入method關鍵字(類似lambda),FCM的#號看起來比較怪異,在我看來,CICE和BGGA更符合胃口,CICE對java語言的變動應該最小,學習曲線也比較平緩,BGGA的=>符號更有函數式語言的味道。閉包的引入,某種程度上能減少敲擊鍵盤的次數并實現一些高階功能,特別是在聚合操作(如filter、map等)和單抽象方法類(如Runnable,Callable)的使用上,但是在現代IDE的自動化幫助下,這個帶來的價值是值的懷疑的。




          posted @ 2008-06-18 00:20 dennis 閱讀(2062) | 評論 (0)編輯 收藏

          僅列出標題
          共56頁: First 上一頁 24 25 26 27 28 29 30 31 32 下一頁 Last 
          主站蜘蛛池模板: 出国| 郁南县| 高邮市| 城步| 洱源县| 平原县| 邯郸县| 米林县| 海淀区| 敦化市| 恩平市| 阿坝县| 伊吾县| 逊克县| 嘉善县| 东辽县| 大化| 芮城县| 曲靖市| 湘潭县| 漳浦县| 大石桥市| 定襄县| 子长县| 万年县| 黔西| 中江县| 新建县| 晴隆县| 凌海市| 平乐县| 舒城县| 永仁县| 彭水| 双城市| 天门市| 蓬安县| 遂昌县| 青岛市| 南昌县| 湖南省|