<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

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

       ets表的底層是由哈希表實現的,不過ordered_set例外,它是由平衡二叉樹實現的。 所以不管是插入還是查找,set的效率要比ordered_set高.采用set還是ordered_set取決于你的需求,當你需要一個有序的集合時,顯然應當采用ordered_set模式。

    duplicate_bag要比bag的效率要高, 因為bag要和原來的記錄比較是否有相同的記錄已經插入. 如果數據量很大,相同的記錄越多,bag的效率就越差.

    一張ets表是由創建它的進程所擁有, 當此進程調用ets:delete或者進程終止的時候, ets表就會被刪除.

    一般情況下, 插入一個元組到一張ets表中, 所有代表這個元組的結構都會被從process的堆棧中,復制到ets表中; 當查找一條記錄時, 結果tuple從ets表中復制到進程的堆棧中。

    但是large binaries卻不是這樣! 它們被存入自已所擁有的off-heap area中。這個區域可以被多個process,ets表,和binaries所共享。它由引用計數的垃圾回收策略管理, 這個策略會跟蹤到底有多少個process/ets表/binaries引用了這個large binaries. 如果引用數為0的話, 此大型二進制數據就會被垃圾回收掉.

    看起來很復雜, 實際結論就是: 兩進程間發送包含大型binary數據的消息其實費用很低, 往ets表插入binary類型元組也很劃算。我們應該盡可能采用binaries來實現字符串或無類型的大數據塊.

    posted @ 2007-09-27 16:33 dennis 閱讀(2192) | 評論 (2)編輯 收藏

    Erlang用于操縱文件I/O的模塊有:
    file模塊:打開、讀、寫、關閉文件已經操作目錄的方法基本都在這里

    filename模塊:提供平臺獨立方式用于操縱文件名

    filelib模塊:file模塊的擴展,提供了更多的實用工具,在file模塊基礎上構建

    io模塊:一系列用于操作打開的文件的方法,解析格式、格式化輸出等等。

    1.打開文件:
    {ok,F}=file:open("data1.dat",read). %讀模式打開
    {ok,F}=file:open("data1.dat",write). %寫模式
    {ok,F}=file:open("data1.dat",[read,write]). %讀、寫、二進制模式

    支持的所有模式參見文檔。

    2.讀?。?br /> (1)如果以一個Erlang term的方式讀取,采用:
    io:read(F,'').
    其中第二個參數是提示符,用于在標準輸入時作為提示。
    這個方法有一個變形read/3
    read(IoDevice, Prompt, StartLine)
    第三個參數用于指定開始行數。

    (2)如果是按字節讀取,文件必須按raw模式打開采用:
    {ok, Data}=file:read(F,100).

    (3)按行讀取:
    io:get_line(F, '').

    (4)讀取整個文件的內容:
    {ok,Binary}=file:read_file("data1.dat").
    注意返回的是一個binary類型

    (5)隨機讀?。?br /> {ok,Binary}=file:pread(F, 22, 46).

    其中第二個參數是開始位置,第三個參數是讀取的長度,返回的也是binary類型。

    3.寫入文件:
    (1)采用io:format/3方法:
    {ok, S} = file:open("test2.dat", write).
    io:format(S, "~s~n", ["Hello readers"]).
    io:format(S, "~w~n", [123]).

    其中的~開頭的字符是一個個格式化命令,比如常見的:
    ~c   anscii碼
    ~f   浮點數
    ~s   字符串
    ~w   Erlang term
    ~p   與~w類似,不過當多行時將自動換行
    ~n   顯然,換行符

    (2)寫入整個文件:
    file:write_file(File, IO)

    其中IO可以為list、integer或者binary類型

    (3)隨機寫入:
    file:pwrite(F, 10, <<"new">>)

    4.關閉文件:
    file:close(F).

    5.目錄操作:
    都是linux命令風格的操作,
    cd("/home/dennis/").  %進入目錄
    file:list_dir(".").   %列出當前目錄文件
    file:make_dir("test").  %創建test目錄
    file:del_dir("test").   %刪除test目錄

    6.獲取文件信息,比如文件大小,最后修改時間等等。調用file:read_file_info/1方法,該方法返回一個file_info記錄類型,里面擁有文件的具體信息,比如type、size等。
    {ok, Facts} =file:read_file_info(File).
    io:format("~s~n",{Facts#file_info.type, Facts#file_info.size}).

    7.復制和刪除文件:
    file:copy(Source, Destination).
    file:delete(File).

        這個筆記僅僅記錄了一些常用到的方法,一些高級的工具方法并沒有涉及,具體參考Erlang的文檔。




    posted @ 2007-09-27 16:03 dennis 閱讀(7945) | 評論 (2)編輯 收藏

        讀完ruby hacking guide第6章,徹底總結下:
    1.在Ruby中,類也是一個對象,因此有實例變量。類的實例變量、類變量、常量都是存儲在RClass struct的iv_tbl中,
    struct RClass {
        struct RBasic basic;
        struct st_table *iv_tbl;
        struct st_table *m_tbl;
        VALUE super;
    };
    iv_tbl的類型是st_table,我在這里用java實現了一下。

    2.用戶自定義類的對象(ruby層次聲明的類的對象)的實例變量存儲在RObject struct的iv_tbl中,
    struct RObject {
      struct RBasic basic;
      struct st_table *iv_tbl;
     };
    調用方法,本質上是一個查表操作。buildin的幾個類,比如String、Array、Hash等(在c層次上實現的類),它們的結構并沒有iv_table,這是從節省內存空間的角度考慮,它們的實例變量存儲在一張全局的st_table中。這張表比較特別,其中的每一個對應的值又是一個st_table,也就是一個“二元結構”,第一層結構是類名與實例變量表的映射,第二層才是實例變量名與實際值的映射。

    3.全局變量存儲在一張全局的st_table中,這個表的鍵就是變量名ID,由于全局變量允許通過alias來設置別名,因此這張全局表中真正存儲的是下面這個struct

    334 struct global_entry {
    335 struct global_variable *var;
    336 ID id;
    337 };

    324 struct global_variable {
    325 int counter; /* 引用計數 */
    326 void *data; /* 變量值 */
    327 VALUE (*getter)(); /* 取值函數 */
    328 void (*setter)(); /* 設置函數 */
    329 void (*marker)(); /* 標記函數 */
    330 int block_trace;
    331 struct trace_var *trace;
    332 };
    (variable.c)

    當不同變量名(通過別名聲明)指向的是同一個全局變量,其實它們指向的是同一個struct global_variable。


    posted @ 2007-09-20 16:17 dennis 閱讀(661) | 評論 (0)編輯 收藏

        今天向公司提出辭職了,考慮這么久,還是決定辭職。我不想浪費大半年時間做維護,大部分時間無所事事,這是我不能接受的。我需要更多的項目經歷來鍛煉自己。在公司這一年,學到的不少,無論從做人還是技術上都有所感悟,接下來確定去廈門,未來將怎么樣?還是充滿希望和憧憬,希望好運吧。

    posted @ 2007-09-20 12:48 dennis 閱讀(569) | 評論 (4)編輯 收藏

         摘要:     update1:添加了remove,removeAll()方法以及getSize()方法     update2:添加了keySet()方法用于迭代       update3:經過測試,StTable類在存儲Integer類型key時,put的速度比HashMap快了接近3倍,而...  閱讀全文

    posted @ 2007-09-18 19:28 dennis 閱讀(1356) | 評論 (0)編輯 收藏

        dreamhead老大曾經討論過這個問題,尋找一種可移植的方式來判斷棧的增長方向,見《棧的增長方向》。今天在讀Ruby hacking guide第5章,介紹alloca函數的部分,提到ruby實現的C語言版本的alloca.c,讀了下代碼,發現這里倒是實現了一個很漂亮的函數用于實現判斷棧的增長方向,利用了局部static變量,與dreamhead老大的想法其實是一致的。
    #include<stdio.h>
    static void find_stack_direction(void);
    static int stack_dir;
    int main(void)
    {
      find_stack_direction();
      
    if(stack_dir==1)
         puts(
    "stack grew upward");
      
    else
         puts(
    "stack grew downward");
      
    return 0;
    }
    static void find_stack_direction (void)
    {
      
    static char   *addr = NULL;   /* address of first
                                       `dummy', once known 
    */
      auto 
    char     dummy;          /* to get stack address */

      
    if (addr == NULL)
        {                           
    /* initial entry */
          addr 
    = &dummy;

          find_stack_direction ();  
    /* recurse once */
        }
      
    else                          /* second entry */
        
    if (&dummy > addr)
          stack_dir 
    = 1;            /* stack grew upward */
        
    else
          stack_dir 
    = -1;           /* stack grew downward */
    }

    posted @ 2007-09-17 16:16 dennis 閱讀(1134) | 評論 (0)編輯 收藏

        ReentrantLock是jdk5引入的新的鎖機制,它與內部鎖(synchronize) 相同的并發性和內存語義,比如可重入加鎖語義。在中等或者更高負荷下,ReentrantLock有更好的性能,并且擁有可輪詢和可定時的請求鎖等高級功能。這個程序簡單對比了ReentrantLock公平鎖、ReentrantLock非公平鎖以及內部鎖的性能,從結果上看,非公平的ReentrantLock表現最好。內部鎖也僅僅是實現統計意義上的公平,結果也比公平的ReentrantLock好上很多。這個程序僅僅是計數,啟動N個線程,對同一個Counter進行遞增,顯然,這個遞增操作需要同步以保證原子性,采用不同的鎖來實現同步,然后查看結果。
    Counter接口:
    package net.rubyeye.concurrency.chapter13;

    public interface Counter {
        
    public long getValue();

        
    public void increment();

    }

    然后,首先使用我們熟悉的synchronize來實現同步:
    package net.rubyeye.concurrency.chapter13;

    public class SynchronizeBenchmark implements Counter {
        
    private long count = 0;

        
    public long getValue() {
            
    return count;
        }

        
    public synchronized void increment() {
            count
    ++;
        }
    }

    采用ReentrantLock的版本,切記要在finally中釋放鎖,這是與synchronize使用方式最大的不同,內部鎖jvm會自動幫你釋放鎖,而ReentrantLock需要你自己來處理。
    package net.rubyeye.concurrency.chapter13;

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;

    public class ReentrantLockBeanchmark implements Counter {

        
    private volatile long count = 0;

        
    private Lock lock;

        
    public ReentrantLockBeanchmark() {
            
    // 使用非公平鎖,true就是公平鎖
            lock = new ReentrantLock(false);
        }

        
    public long getValue() {
            
    // TODO Auto-generated method stub
            return count;
        }

        
    public void increment() {
            lock.lock();
            
    try {
                count
    ++;
            } 
    finally {
                lock.unlock();
            }
        }

    }

        寫一個測試程序,使用CyclicBarrier來等待所有任務線程創建完畢以及所有任務線程計算完成,清單如下:
    package net.rubyeye.concurrency.chapter13;

    import java.util.concurrent.CyclicBarrier;

    public class BenchmarkTest {
        
    private Counter counter;

        
    private CyclicBarrier barrier;

        
    private int threadNum;

        
    public BenchmarkTest(Counter counter, int threadNum) {
            
    this.counter = counter;
            barrier 
    = new CyclicBarrier(threadNum + 1); //關卡計數=線程數+1
            this.threadNum = threadNum;
        }

        
    public static void main(String args[]) {
            
    new BenchmarkTest(new SynchronizeBenchmark(), 5000).test();
           
    //new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();
            //new BenchmarkTest(new ReentrantLockBeanchmark(), 5000).test();   
        }

        
    public void test() {
            
    try {
                
    for (int i = 0; i < threadNum; i++) {
                    
    new TestThread(counter).start();
                }
               
    long start = System.currentTimeMillis();
                barrier.await(); // 等待所有任務線程創建
                barrier.await(); // 等待所有任務計算完成
                long end = System.currentTimeMillis();
                System.out.println(
    "count value:" + counter.getValue());
                System.out.println(
    "花費時間:" + (end - start) + "毫秒");
            } 
    catch (Exception e) {
                
    throw new RuntimeException(e);
            }
        }

        
    class TestThread extends Thread {
            
    private Counter counter;

            
    public TestThread(final Counter counter) {
                
    this.counter = counter;
            }

            
    public void run() {
                
    try {
                    barrier.await();
                    
    for (int i = 0; i < 100; i++)
                        counter.increment();
                    barrier.await();
                } 
    catch (Exception e) {
                    
    throw new RuntimeException(e);
                }
            }
        }
    }

    分別測試一下,

    將啟動的線程數限定為500,結果為:
    公平ReentrantLock:      210 毫秒
    非公平ReentrantLock :   39  毫秒
    內部鎖:                          39 毫秒

    將啟動的線程數限定為1000,結果為:
    公平ReentrantLock:      640 毫秒
    非公平ReentrantLock :   81 毫秒
    內部鎖:                           60 毫秒

    線程數不變,test方法中的循環增加到1000次,結果為:
    公平ReentrantLock:      16715 毫秒
    非公平ReentrantLock :   168 毫秒
    內部鎖:                           639  毫秒

    將啟動的線程數增加到2000,結果為:
    公平ReentrantLock:      1100 毫秒
    非公平ReentrantLock:   125 毫秒
    內部鎖:                           130 毫秒

    將啟動的線程數增加到3000,結果為:
    公平ReentrantLock:      2461 毫秒
    非公平ReentrantLock:   254 毫秒
    內部鎖:                           307 毫秒

    啟動5000個線程,結果如下:
    公平ReentrantLock:      6154  毫秒
    非公平ReentrantLock:   623   毫秒
    內部鎖:                           720 毫秒

    非公平ReentrantLock和內部鎖的差距,在jdk6上應該縮小了,據說jdk6的內部鎖機制進行了調整。

    posted @ 2007-09-14 17:15 dennis 閱讀(8126) | 評論 (2)編輯 收藏

        Ruby語言中的String是mutable的,不像java、C#中的String是immutable的。比如
           str1="abc"
           str2="abc"
    在java中,對于字面量的字符串,jvm內部維持一張表,因此如果在java中,str1和str2是同一個String對象。而在Ruby中,str1和str2是完全不同的對象。同樣,在java中對于String對象的操作都將產生一個新的對象,而Ruby則是操縱同一個對象,比如:
           str="abc"
           str.concat("cdf")
    此時str就是"abccdf"。Ruby對String是怎么處理的呢?我們只談談c ruby中的實現,有興趣的先看看這篇文章《管窺Ruby——對象基礎》。在ruby.h中我們可以看到String對象的結構,Ruby中的對象(包括類也是對象)都是一個一個的struct,String也不能例外:
    struct RString {
        struct RBasic basic;
        long len;
        char *ptr;
        union {
          long capa;
          VALUE shared;
        } aux;
    };
    //ruby.h

        顯然,len是String的長度;ptr是一個char類型的指針,指向實際的字符串;然后是一個聯合,這個稍后再說。如果你看看ruby.h可以發現,幾乎所有定義的對象結構都有一個struct RBasic。顯然,struct RBasic包含由所有對象結構體共享的一些重要信息的??纯碦Basic:

    struct RBasic {
     unsigned long flags;
     VALUE klass;
    };
    其中的flags是一個多用途的標記,大多數情況下用于記錄結構體的類型,ruby.h中預定義了一些列的宏,比如T_STRING(表示struct RString),T_ARRAY(表示struct RArray)等。Klass是一個VALUE類型,VALUE也是unsigned long,可以地將它當成指針(一個指針4字節,綽綽有余了),它指向的是一個Ruby對象,這里以后再深入。
        那么聯合aux中的capa和shared是干什么用的呢?因為Ruby的String是可變的,可變意味著len可以改變,我們需要每次都根據len的變換來增減內存(使用c中的realloc()函數),這顯然是一個很大的開銷,解決辦法就是預留一定的空間,ptr指向的內存大小略大于len,這樣就不需要頻繁調用realloc了,aux.capa就是一個長度,包含額外的內存大小。那么aux.shared是干什么的呢?這是一個VALUE類型,說明它是指向某個對象。aux.shared其實是用于加快字符串的創建速度,在一個循環中:
    while true do  # 無限重復
    a = "str" # 以“str”為內容創建字符串,賦值給a
    a.concat("ing") # 為a所指向的對象添加“ing”
    p(a) # 顯示“string”
    end
    每次都重新創建一個"str"對象,內部就是重復創建一個char[],這是相當奢侈,aux.shared就是用于共享char[],
    以字面量創建的字符串會共享一個char[],當要發生變化時,將字符串復制到一個非共享的內存中,變化針對這
    個新拷貝進行,這就是所謂的“copy-on-write"技術。解釋了String的內部構造,貌似還沒有介紹String是怎么
    實現mutable,我們寫一個Ruby擴展測試下,我們想寫這樣一個Ruby類:
    class Test
    def test
    str="str"
    str.concat("ing")
    end
    end
    對應的c語言代碼就是:
    #include<stdio.h>
    #include 
    "ruby.h"

    static VALUE t_test(VALUE self)
    {
      VALUE str;
      str
    =rb_str_new2("str");
      printf(
    "before concat: str:%p, str.aux.shared:%p, str.ptr:%s"n",str,
           (RSTRING(str)->aux).shared,RSTRING(str)->ptr);
      rb_str_cat2(str,
    "ing");
      printf(
    "after concat: str:%p, str.aux.shared:%p, str.ptr:%s"n",
           str,(RSTRING(str)->aux).shared,RSTRING(str)->ptr);
      
    return self;
    }
    VALUE cTest;
    void Init_string_hack(){
      cTest
    =rb_define_class("Test",rb_cObject);
      rb_define_method(cTest,
    "test",t_test,0);

    }
    //string_hack.c
       rb_define_class函數定義了一個類Test,rb_define_method將t_test方法以test的名稱添加到Test類。在
    t_test中,通過rb_str_new2每次生成一個RString結構,然后通過rb_str_cat2將str與"ing"連接起來,添加
    了一些打印用于跟蹤。利用mkmf產生Makefile,寫一個extconf.rb
    require 'mkmf'
    create_makefile("string_hack");
    執行ruby extconf.rb,將產生一個Makefile,執行make,生成一個string_hack.so的鏈接庫。擴展寫完了,通過
    ruby調用:
    require 'string_hack"
    t=Test.new
    (1..3).each{|i| t.test}
    輸出:
    before concat: str:0x40098a40, str.aux.shared:0x3, str.ptr:str
    after concat: str:0x40098a40, str.aux.shared:0x8, str.ptr:string
    before concat: str:0x40098a2c, str.aux.shared:0x3, str.ptr:str
    after concat: str:0x40098a2c, str.aux.shared:0x8, str.ptr:string
    before concat: str:0x40098a18, str.aux.shared:0x3, str.ptr:str
    after concat: str:0x40098a18, str.aux.shared:0x8, str.ptr:string
    從結果可以看出,在str concat之前之后,str指向的位置沒有改變,改變的僅僅是str中ptr指向的字符串的值
    ,看看rb_str_cat2函數的實現就一目了然了:
    VALUE rb_str_cat(str, ptr, len)
        VALUE str;
        const char *ptr;
        long len;
    {
        if (len < 0) {
            rb_raise(rb_eArgError, "negative string size (or size too big)");
        }
        if (FL_TEST(str, STR_ASSOC)) {
            rb_str_modify(str);
            REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
            memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
            RSTRING(str)->len += len;
            RSTRING(str)->ptr[RSTRING(str)->len] = '"0'; /* sentinel */
            return str;
        }
        return rb_str_buf_cat(str, ptr, len);
    }
    VALUE rb_str_cat2(str, ptr)
        VALUE str;
        const char *ptr;
    {
        return rb_str_cat(str, ptr, strlen(ptr));
    }
    //string.c



    posted @ 2007-09-12 09:43 dennis 閱讀(1931) | 評論 (0)編輯 收藏

        在javaeye上看到的轉貼,原始出處不知道在何處了。50本世界名著一句話總結,粗粗掠過,自己也就看了其中的15本左右,而給我留下最深印象的仍然是卡夫卡的《變形記》,仍然記的第一次閱讀時心靈的悸動,乃至后來看村上的《海邊的卡夫卡》,隱喻中的現實真實而殘酷。

        1.神要是公然去跟人作對,那是任何人都難以對付的。(《荷馬史詩》)

    2.生存還是毀滅,這是一個值得思考的問題。(《哈姆霄特》)

    3.善良人在追求中縱然迷惘,卻終將意識到有一條正途。(《浮士德》)

    4.認識自己的無知是認識世界的最可靠的方法。(《隨筆集》)

    5.你以為我貧窮、相貌平平就沒有感情嗎?我向你發誓,如果上帝賦予我財富和美貌,我會讓你無法離開我,就像我現在無法離開你一樣。雖然上帝沒有這么做,可我們在精神上依然是平等的。(《簡-愛》)

    6.大人都學壞了,上帝正考驗他們呢,你還沒有受考驗,你應當照著孩子的想法生活。(《童年》)

    7,你越沒有心肝,就越高升得快,你毫不留情地打擊人家,人家就怕你。只能把男男女女當作驛馬,把它們騎得筋疲力盡,到了站上丟下來,這樣你就能達到欲望的最高峰。(《高老頭》)

    8.我只想證明一件事,就是,那時魔鬼引誘我,后來又告訴我,說我沒有權利走那條路,因為我不過是個虱子,和所有其余的人一樣。(《罪與罰》)

    9.你瞧,桑丘?潘沙朋友,那邊出現了三十多個大得出奇的巨人。(《堂-吉訶德》)

    10.我并不愿意你受的苦比我受的還大,希斯克利夫。我只愿我們永遠不分離:如果我有一句話使你今后難過,想想我在地下也感到一樣的難過,看在我自己的份上,饒恕我吧!(《呼嘯山莊》)

    11.幸福的家庭是相同的,不幸的家庭各有各的不同。(《安娜-卡列尼娜》)

    12.唉,奴隸般的意大利,你哀痛之逆旅,你這暴風雨中沒有舵手的孤舟,你不再是各省的主婦,而是妓院!(《神曲》)

    13.將感情埋藏得太深有時是件壞事。如果一個女人掩飾了對自己所愛的男子的感情,她也許就失去了得到他的機會。(《傲慢與偏見》)

    14.鐘聲又鳴響了……一聲又一聲,靜謐而安詳,即使在女人做新娘的那個好月份里,鐘聲里也總帶有秋天的味道。(《喧囂與騷動》)

    15.一個人并不是生來要被打敗的,你盡可以把他消滅掉,可就是打不敗他。(《老人與海》)

    16.當然,行是行的,這固然很好,可是千萬別鬧出什么亂子來啊。(《套中人》)

    17.面包!面包!我們要面包!(《萌芽》)

    18.我從沒有愛過這世界,它對我也一樣。(《拜倫詩選》)

    19. 愛情應該給人一種自由感,而不是囚禁感。(《兒子與情人》)

    20.暴風雨將要在那一天,甚至把一些槲樹吹倒,一些教堂的高塔要倒塌,一些宮殿也將要動搖!(《海涅詩選》)

    21.自己的行為最惹人恥笑的人,卻永遠是最先去說別人壞話的人。(《偽君子》)

    22.這時一種精神上的感慨油然而生,認為人生是由啜泣、抽噎和微笑組成的,而抽噎占了其中絕大部分。(《歐-亨利短篇小說選》)

    23.歷史喜愛英勇豪邁的事跡,同時也譴責這種事跡所造成的后果。(《神秘島》)

    24.整個下半天,人都聽憑羊脂球去思索。不過本來一直稱呼她作“夫人”,現在卻簡單地稱呼她作“小姐”了,誰也不很知道這是為著什么,仿佛她從前在 評價當中爬到了某種地位,現在呢,人都想把她從那種地位拉下一級似的,使她明白自己的地位是尚叩摹?(《莫泊桑短篇小說選》)

    25.如果冬天來了,春天還會遠嗎? (《雪萊詩選》)

    26.我明白了,我已經找到了存在的答案,我惡心的答案,我整個生命的答案。其實,我所理解的一切事物都可以歸結為荒誕這個根本的東西。(《惡心》)

    27.世界上有這樣一些幸福的人,他們把自己的痛苦化作他人的幸福,他們揮淚埋葬了自己在塵世間的希望,它卻變成了種子,長出鮮花和香膏,為孤苦伶仃的苦命人醫治創傷。(《湯姆叔叔的小屋》)

    28.當格里高?薩姆莎從煩躁不安的夢中醒來時,發現他在床上變成了一個巨大的跳蚤。(《變形記》)

    29.當現實折過來嚴絲合縫地貼在我們長期的夢想上時,它蓋住了夢想,與它混為一體,如同兩個同樣的圖形重疊起來合而為一一樣。(《追憶似水年華》)

    30.人與人之間,最可痛心的事莫過于在你認為理應獲得善意和友誼的地方,卻遭受了煩擾和損害。(《巨人傳》)

    31.現在我說的您要特別注意聽:在別人心中存在的人,就是這個人的靈魂。這才是您本身,才是您的意識在一生當中賴以呼吸、營養以至陶醉的東西,這也就是您的靈魂、您的不朽和存在于別人身上的您的生命。(《日瓦戈醫生》)

    32.美德猶如名香,經燃燒或壓榨而其香愈烈,蓋幸運最能顯露惡德而厄運最能顯露美德。(《培根論說文集》)

    33.親愛的艾妮斯,我出國,為了愛你,我留在國外,為了愛你,我回國,也是為了愛你!(《大衛-科波菲爾》)

    34.強迫經常使熱戀的人更加鐵心,而從來不能叫他們回心轉意。(《陰謀與愛情》)

    35.在各種事物的常理中,愛情是無法改變和阻擋的,因為就本性而言,愛只會自行消亡,任何計謀都難以使它逆轉。(《十日談》)

    36.只要你是天鵝蛋,就是生在養雞場里也沒有什么關系。(《安徒生童話》)

    37.就投機鉆營來說,世故的價值永遠是無可比擬的。(《死魂靈》)

    38.誰都可能出個錯兒,你在一件事情上越琢磨得多就越容易出錯。(《好兵帥克歷險記》)

    39.我們經歷著生活中突然降臨的一切,毫無防備,就像演員進入初排。如果生活中的第一次彩排便是生活本身,那生活有什么價值呢?(《生命中不能承受之輕》)

    40.他發現了人類行為的一********自己還不知道——那就是,為了要使一個大人或小孩極想干某樣事情,只需要設法把那件事情弄得不易到手就行了。(《湯姆-索亞歷險記》)

    41.對有信仰的人,死是永生之門。(《失樂園》)

    42.有一個傳說,說的是有那么一只鳥兒,它一生只唱一次,那歌聲比世上所有一切生靈的歌聲都更加優美動聽。(《荊棘鳥》)

    43.離開一輩子后,他又回到了自己出生的那片土地上。從小到大,他一直是那個地方的目擊者。(《尤利西斯》)

    44.同上帝保持聯系是一碼事,他們都贊同這一點,但讓上帝一天二十四小時都待在身邊就是另一碼事了。(《第二十二條軍規》)

    45.在甜蜜的夢鄉里,人人都是平等的,但是當太陽升起,生存的斗爭重新開始時,人與人之間又是多么的不平等。(《總統先生》)

    46.開發人類智力的礦藏是少不了要由患難來促成的。(《基度山伯爵》)

    47.離你越近的地方,路途越遠;最簡單的音調,需要最艱苦的練習。(《泰戈爾詩選》)

    48.悲傷使人格外敏銳。(《約翰-克里斯朵夫》 )

    49.我在女人跟前經常失敗,就是由于我太愛她們了。(《懺悔錄》)

    50.她睜大一雙絕望的眼睛,觀看她生活的寂寞。她像沉了船的水手一樣,在霧蒙蒙的天邊,遙遙尋找白帆的蹤影。(《包法利夫人》)


    posted @ 2007-09-09 15:04 dennis 閱讀(475) | 評論 (1)編輯 收藏

        jdk5引入的concurrent包來自于Doug Lea的卓越貢獻。最近我在查找服務器OOM的原因之后,決定采用這個包重寫應用中一個servlet,這個servlet調用了一個阻塞方法,當被阻塞之后,服務器中的線程數(因為阻塞了,后續請求不斷地新增線程)突然增加導致了服務器當機,因此決定采用一個線程池,并且設置超時,如果阻塞方法超過一定時間就取消線程。因為我們的項目仍然跑在jdk 1.4.2上面,短期內不可能升級到jdk5,還是要利用這個并發包。去這里下載源碼并自己打包成jar,加入項目的lib,然后利用PooledExecutorTimedCallable來實現我們的需求。首先是線程池,相當簡單:
    import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
    import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
    /**
     * <p>類說明:線程池</p>
     * <p>注意事項:</p>
     * <pre></pre>
     * <p>創建日期:Sep 7, 2007 1:25:33 PM</p>
    @author:dennis zane
     * 
    @version $Id:$
     
    */
    public class MyThreadPool{
        
    private static PooledExecutor exec = new PooledExecutor(new BoundedBuffer(
                
    20), 30);
        
    static {
            exec.setKeepAliveTime(
    1000 * 60 * 5);
            exec.createThreads(
    5);
            exec.setMinimumPoolSize(
    4);
        }

        
    public static void execute(final Runnable r)  throws InterruptedException{
        
        exec.execute(r);
       
    }

        
    public static void shutdown() {
            exec.shutdownAfterProcessingCurrentlyQueuedTasks();
            exec 
    = null;
        }

    }


        靜態初始化并設置一個PoolExecutor,設置空閑線程的存活時間為5分鐘,設置最小線程數為4,最大線程數為30,一開始創建5個線程以待使用(根據各自的應用調整這些參數),另外提供了shutdown方法以供ServeltContextListener的contextDestroyed方法調用以關閉線程池。那么,結合TimedCallable來實現提交線程的超時機制,調用類似:
               //設置超時時間
               private static final long timeout = 1000;
               ......
               ......
           try{
               Callable callable = new Callable() {
                    
    public Object call() {
                       
    return new YourProgram().run();                   
                    }
                };
                TimedCallable timedCallable 
    = new TimedCallable(callable, timeout);
                FutureResult future 
    = new FutureResult();
                Runnable cmd 
    = future.setter(timedCallable);
                
    //提交給線程池來執行
                MyThreadPool.execute(cmd);
                //獲取任務結果
                YourObject obj
    = (YourObject) future.get();
                ......
                ......
             }
    catch (InterruptedException e) {
                if (e instanceof TimeoutException) {
                     log.error("任務超時");
                      ...
                 }
             }catch(InvocationTargetException e)
             {
                //清理任務..
             }
             ......
    如果不是很理解這段代碼,那么也許你應該先看看jdk5引入的Future、FutureTask等類,或者看看這里的文檔。對于超時時間的大小估算,你應當在生產環境中計算該阻塞方法的調用時間,正常運行一段時間,利用腳本語言(比如ruby、python)分析日志以得到一個調用花費時間的最大值作為timeout,這里的單位是毫秒。而線程池大小的估算,要看你提交給線程執行的任務的類型:如果是計算密集型的任務,那么線程池的大小一般是(cpu個數+1);如果是IO密集型的任務(一般的web應用皆是此類),那么估算有一個公式,
    假設N-cpu是cpu個數,U是目標CPU使用率,W/C是任務的等待時間與計算時間的比率,那么最優的池大小等于:
    N-threads=N-cpu*U*(1+W/C)
       

    posted @ 2007-09-09 14:23 dennis 閱讀(3873) | 評論 (0)編輯 收藏

    僅列出標題
    共56頁: First 上一頁 33 34 35 36 37 38 39 40 41 下一頁 Last 
    主站蜘蛛池模板: 国产高清在线免费视频| 麻豆69堂免费视频| a色毛片免费视频| 国产美女无遮挡免费视频网站| 2021在线永久免费视频| 亚洲自偷自偷图片| 美女羞羞免费视频网站| 久久九九兔免费精品6| 久久精品亚洲综合一品| 黄色短视频免费看| 久久久久亚洲av毛片大| 色网站在线免费观看| 在线观看免费污视频| 亚洲一区二区三区在线观看蜜桃| 久久亚洲AV成人无码国产最大| 巨胸喷奶水www永久免费| 亚洲国产成人五月综合网| 国产精品亚洲综合天堂夜夜| 欧洲精品免费一区二区三区| 亚洲一区二区三区在线| 毛片a级毛片免费播放下载| 涩涩色中文综合亚洲| 在线免费观看色片| 亚洲xxxx视频| 日本黄色免费观看| 亚洲GV天堂GV无码男同 | 鲁丝片一区二区三区免费| 亚洲国产91精品无码专区| 免费夜色污私人影院网站电影 | 在线免费观看色片| 国产午夜亚洲精品| 国产特级淫片免费看| 暖暖免费中文在线日本| 亚洲宅男天堂在线观看无病毒| 337P日本欧洲亚洲大胆精品| 亚洲XX00视频| 99re6在线视频精品免费| 亚洲最大成人网色| 91在线视频免费播放| 亚洲AV无码一区二区三区久久精品| av永久免费网站在线观看|