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

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

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

    china-pub購書網址:http://www.china-pub.com/computers/common/info.asp?id=34017

    1、總體感受
    a) 這本書主要介紹的是intel平臺下的多核程序設計技術,Windows介紹較多,Linux介紹較少,Java更少。作者是Intel公司的平臺架構師,我們知道wintel聯盟,書中的內容如此分布也是正常。
    b) 此書讓我懂得了很多硬件方面的并行知識。
    c) 此書介紹Windows API中和并發相關的部分,很詳盡,比Jeffrey Richter的《Windows核心編成》有深度多了,也精辟多了。顯然《多核程序設計》作者屬于有經驗的工程師,Jeffrey Richter只是一個寫手,兩者沒有可比性。不過這方面的知識偶早已涉獵,當作復習一遍罷了。
    d) 此書偏向底層,硬件和操作系統層面。更高層面的技術介紹較少。
    e) 第一次了解OpenMP技術的一些細節。以前只聽說,也沒查過任何相關資料,在此書中看到了相關部分,挺有意思的,感覺那些語法很有趣。Herb Sutter也是要在語法方面動手。反正我在有了一個粗淺認識之后,覺得很有意思。

    -------------------------

    2、并發流程控制
    Fence
    在Java 中對應的是java.util.concurrent.CountDownLatch。最初接觸CountDownLatch的時候,由于其實現很簡單, 當時覺得是一個可有可無的工具類。但后來在不同的場景多次使用,發現很有用。在此書中再次發現類似的Fence,用于在共享存儲多處理器或者多核環境中, 確保存儲操作的一致性。我猜這屬于業界并發流控制的典型手段了。


    Barrier
    在Java中對應的是java.util.concurrent.CyclicBarrier。在應用程序中,一個場景就是和定時器結合使用,countDown、await、reset,做定時定量批量處理。
    我猜這也屬于業界并發流程控制的典型手段了。

    (CountDownLatch和CycliBarrier的實現代碼都很簡單,但很有用,他們都屬于并發流程控制的典型手段)

    -------------------------

    3、非阻塞算法
    InterLocked在Java中對應的是java.util.concurrent.atomic.xxx
    書中提到了cache行乒乓球現象導致的性能問題,提高了非阻塞算法的復雜性問題。

    關于性能問題,developerworks上有一片文章,有測試數據:
    《Java 理論與實踐: 流行的原子》 (http://www.ibm.com/developerworks/cn/java/j-jtp11234/index.html)
    文章中的測試數據表明,直接使用atomic在1個和2個處理器時是最好的,4個處理器以上,使用java.util.concurrent.locks.ReentrantLock性能更好。

    java.util.concurrent包,提供了很多高級的概念,隱藏了非阻塞算法帶來的復雜度,其底層框架達到了最佳性能。

    -------------------------

    4、任務分解、數據分解以及數據流分解
    此書中明確提出了這三個概念,很有用,讓我在這方面的知識概念清晰化了。

    任務分解
    Java 中的Executor,提供了任務分解的手段和模式。任務分解提交給Executor執行。java.util.concurrent中提供了 Future,用于任務提交者和Executor之間的協調。Future是一種很好的手段,在很多涉及并發的庫都提供。例如C++網絡并發庫中提供了 Future,Herb Sutter要在Visual C++中引入Future。

    數據分解
    數據分解的手段很多也很常見。 Java中,提供了一種高級的數據分解協同模式java.util.concurrent.Exchanger這個類。早在Java SE 5.0時,Exchanger只支持2Parties,Java SE 6.0支持n parties。偶想象過一些很酷的應用場景,寫過模擬測試,但一直沒有機會用于實際開發中。

    數據流分解
    書中提到了眾多周知的producer/consumer問題。
    其實java.util.concurrent.Exchanger類,既有數據分解,又有數據流分解,exchanger中的producer和consumer的角色會互換的,很有意思。

    -------------------------

    5、作為Java程序員的思考
    Java SE 5.0之后,提供了util.concurrent包,功能齊全,性能卓越,非常優秀。從此書來看,業界流行的流程控制手段和并發程序設計方法一個不落。我們應該感謝偉大的Doug Lea,他為我們帶了一個如此完美的并發庫!
    posted @ 2007-04-26 07:08 溫少的日志 閱讀(3290) | 評論 (0)編輯 收藏
     

    一旦方案想清楚,剩余部分的工作效率瓶頸就在于你的手速了。最近一直看起點中文網上的《師士傳說》,主角葉重一個強項就是手速。

    最基本的就是盲打。不會盲打的通常屬于“編碼低能兒”。身邊也有不會盲打的朋友,他們通常都有一個問題,就是眼高手低,說說還行,動手就不行。當然他們能夠在IT研發領域還混得很好,是因為在其他方面擁有優秀的能力。

    熟練掌握快捷鍵是關鍵。鍵盤和鼠標之間通常有較大的距離,手經常在鍵盤和鼠標之間移動,會降低效率,也容易導致疲勞,用鼠標過多,也容易導致齷齪的鼠標手。解決這個問題的辦法,就是純鍵盤操作,其實很多IDE的快捷鍵功能強大,足以讓你純鍵盤操作,高效率編碼。

    我比較熟悉的IDE是Eclipse,就以Eclispse來說吧。

    Eclipse的keys列表中,屬于Eclipse本身有180多個快捷鍵,要提高編碼速度,就應該熟練使用其中絕大多數。

    練習的辦法:
    1、在Windows/Preferences/General/keys中,使用Export,把快捷鍵導出,導出的格式是csv格式,Windows下可以用Excel直接打開,Linux下可以用OpenOffice打開,打開時選擇分隔符為“,”。

    2、挨個練習使用。每天練習一部分,反復練習,堅持一段時間。

    3、開始的時候,把鼠標放到一個不方便使用的角落,盡量不要讓自己用鼠標。

    4、快捷鍵的組合使用需要加強訓練。在不同場景下,認真考慮用怎樣的組合快捷鍵最高效。

    如此堅持一段時間之后,編碼的過程會很流暢,速度就會大大提高。



    posted @ 2007-04-25 07:41 溫少的日志 閱讀(3222) | 評論 (25)編輯 收藏
     

    這是一個很老的問題了,經常在論壇上看到,很多人也寫了相關的文章。我在這方面擁有較多的經驗,我也談一下我的看法吧。

    我曾經實現過金蝶EAS BOS的多數據支持引擎,腳本引擎,也作過O-R Mapping的預研工作,曾經對多個O-R Mapping產品做過研究。

    C++、Java、C#都源自Algol,這系列語言也稱為Imperative語言,中文翻譯為命令式語言。命令式語言建立在馮*諾依曼體系結構上,程序員必須處理變量管理、變量復制。這樣的結果是增加了執行的效率,但帶來了程序開發的艱苦。

    LISP、Schema、Haskell等語言屬于函數式語言,函數式語言基于數學函數,不使用變量或者賦值語句產生結果,使用函數的應用、條件表示和遞歸作為執行控制。函數式語言是更高級的程序設計語言,和命令式語言相比,編寫更少的代碼,更高的開發效率,這是函數式語言的明確有點。很多編程技術都首先應用于函數式語言,例如范型、垃圾收集等。很多函數式語言都增加了一些命令式語言的特征,增加效率和易用性。

    SQL語言是一個領域專用語言,專門用于處理關系數據。他具備一些函數式語言的特征,在處理關系數據方面非常直觀和簡介。在處理選擇、投影、聚合、排序等等操作方面,顯然比在Java或者C#中要方便得多。SQL也是易學易用。很多非程序員都掌握SQL,在金蝶,大多需求人員都熟練掌握SQL。SQL的解釋需要損耗一定的性能,在對性能極端要求的情況下,通常不使用關系數據庫。例如Google Account采用Berkeley DB等。

    現在關系數據庫已經發展很成熟,數據庫的一些技術發展得很好,包括事務等,其中一些從數據庫中發展起來的技術,還應用到操作系統中了。在前些年面向對象技術狂熱的時候,作了很多面向對象數據庫的研究,但是都沒有取得較大的成功。在主流的關系數據庫中,大多都包括了面向對象的支持,例如Oracle、Sybase,都具備了很豐富的面向對象功能,但是很少任用。

    現在有人跟我說起db4o這樣的數據庫,我認為db4o不會取得成功,因為他在錯誤的方向發展。

    現在關系數據庫最流行,最流行的應用開發語言包括Java、C#等,都是面向對象命令式語言。開發語言需要訪問關系數據庫,需要轉換,轉換的過程比較繁瑣,于是就誕生了O-R Mapping技術。這是一種妥協的結果,面向對象技術在數據庫領域無法取得成功,在面向對象開發語言中,就需要一種對象-關系映射技術。我相信,這種妥協產生的技術,會越來越流行。

    我也認為,這是一個正確的選擇。就如高級語言不會嘗試取代匯編,無論高級語言有多好,最多在其上增加抽象層。例如Java使用bytecode、C#使用IL這樣,使用一種抽象層,而不是嘗試取代匯編。

    O-R Mapping技術除了簡單映射之外,需要一種OQL,混合SQL和面向對象特征,提供映射方便的同時,保留關系數據庫提供的強大功能。例如聚合、排序等關系運算必須在OQL中提供。由于程序中的返回結果,有時不需要映射成對象,所以OQL必須提供另外一種功能,數據查詢。很多O-R Mappping產品都提供了基于對象的OQL和基于數據的OQL。

    這導致包括三個部分:
    1、應用程序使用OQL
    2、O-R Mapping解釋或者編譯OQL
    3、對象數據庫負責數據處理

    如果O-R Mapping使用解釋的方式處理OQL,則會包括產生SQL、組裝對象等操作。效率通常都不會很好,現在的O-R Mapping產品基本都是基于解釋的方式處理。

    如果O-R Mapping使用編譯的方式,可以優化產生SQL,動態創建SQL存儲過程,減少SQL交互的過程,能夠獲得很好的性能,可以做到比絕
    大多數人直接使用SQL性能都要好。我曾經做過一個實驗性的實現,取得很好的效果,可惜由于種種原因,沒有繼續下去。

    我認為,下一代的O-R Mapping產品,都將會采用編譯的方式,因為在很多情形下,特別是復雜對象的處理方面,可以有大幅度的性能提升,在某些場景下,可以數倍甚至數十倍的性能提升。

    一直不是很看好Hibernate,因為其主要作者gavin對編譯技術不了解,2.x版本的HQL語法很搞笑,實現也是很搞笑的,簡單的文本替換,看到讓人目瞪口呆。3.0之后加入了HQL的AST(抽象語法樹),但這不是他本人的做的,其他愛好者加入進來,3.1還是沒有很好融合進來。之后的版本我就沒有繼續關注了。

    我覺得O-R Mapping完全就是一種編譯技術,不懂編譯技術的人去作這件事清總會有些不妥。這不單是Hibernate的問題,也是其他O-R Mapping產品的問題。


    我的觀點:
    1、Java、C#、C++等語言在處理關系數據方面沒有優勢。SQL是關系數據處理的領域專用語言(DSL),更適合處理關系數據,提供強大的功能。
    2、關系數據是主流,希望應用開發人員使用O-R Mapping,而不懂關系數據庫,這是不現實的。
    3、O-R Mapping技術還有很大發展空間,以后在功能、性能等方面都會有重大提升,最終成熟。


    溫少 2007-04-23 08:18 發表評論

    文章來源:http://www.cnblogs.com/jobs/archive/2007/04/23/723297.html
    posted @ 2007-04-23 08:23 溫少的日志 閱讀(1175) | 評論 (2)編輯 收藏
     

    在操作系統中,有兩種不同的方法提供線程支持:用戶層的用戶線程,或內核層的內核線程。

    其中用戶線程在內核之上支持,并在用戶層通過線程庫來實現。不需要用戶態/核心態切換,速度快。操作系統內核不知道多線程的存在,因此一個線程阻塞將使得整個進程(包括它的所有線程)阻塞。由于這里的處理器時間片分配是以進程為基本單位,所以每個線程執行的時間相對減少。

    內核線程由操作系統直接支持。由操作系統內核創建、調度和管理。內核維護進程及線程的上下文信息以及線程切換。一個內核線程由于I/O操作而阻塞,不會影響其它線程的運行。

    Java線程的實現是怎樣的呢?我們通過SUN Java 6的源碼了解其在Windows和Linux下的實現。

    在Windows下的實現,os_win32.cpp中
    // Allocate and initialize a new OSThread
    bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
      unsigned thread_id;

      
    // Allocate the OSThread object
      OSThread* osthread = new OSThread(NULL, NULL);
      
    if (osthread == NULL) {
        
    return false;
      }

      
    // Initial state is ALLOCATED but not INITIALIZED
      {
        MutexLockerEx ml(thread
    ->SR_lock(), Mutex::_no_safepoint_check_flag);
        osthread
    ->set_state(ALLOCATED);
      }
      
      
    // Initialize support for Java interrupts
      HANDLE interrupt_event = CreateEvent(NULL, truefalse, NULL);
      
    if (interrupt_event == NULL) {
        delete osthread;
        
    return NULL;
      }
      osthread
    ->set_interrupt_event(interrupt_event);
      osthread
    ->set_interrupted(false);
      
      thread
    ->set_osthread(osthread);
      
      
    if (stack_size == 0) {
        
    switch (thr_type) {
        
    case os::java_thread:
          
    // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
          if (JavaThread::stack_size_at_create() > 0)
            stack_size 
    = JavaThread::stack_size_at_create();
          
    break;
        
    case os::compiler_thread:
          
    if (CompilerThreadStackSize > 0) {
            stack_size 
    = (size_t)(CompilerThreadStackSize * K);
            
    break;
          } 
    // else fall through:
            
    // use VMThreadStackSize if CompilerThreadStackSize is not defined
        case os::vm_thread:
        
    case os::pgc_thread:
        
    case os::cgc_thread:
        
    case os::watcher_thread:
          
    if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
          
    break;
        }
      }

      
    // Create the Win32 thread
      
    //
      
    // Contrary to what MSDN document says, "stack_size" in _beginthreadex()
      
    // does not specify stack size. Instead, it specifies the size of
      
    // initially committed space. The stack size is determined by
      
    // PE header in the executable. If the committed "stack_size" is larger
      
    // than default value in the PE header, the stack is rounded up to the
      
    // nearest multiple of 1MB. For example if the launcher has default
      
    // stack size of 320k, specifying any size less than 320k does not
      
    // affect the actual stack size at all, it only affects the initial
      
    // commitment. On the other hand, specifying 'stack_size' larger than
      
    // default value may cause significant increase in memory usage, because
      
    // not only the stack space will be rounded up to MB, but also the
      
    // entire space is committed upfront.
      
    //
      
    // Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'
      
    // for CreateThread() that can treat 'stack_size' as stack size. However we
      
    // are not supposed to call CreateThread() directly according to MSDN
      
    // document because JVM uses C runtime library. The good news is that the
      
    // flag appears to work with _beginthredex() as well.

    #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
    #define STACK_SIZE_PARAM_IS_A_RESERVATION  (0x10000)
    #endif

      HANDLE thread_handle 
    =
        (HANDLE)_beginthreadex(NULL,
                               (unsigned)stack_size,
                               (unsigned (__stdcall 
    *)(void*)) java_start,
                               thread,
                               CREATE_SUSPENDED 
    | STACK_SIZE_PARAM_IS_A_RESERVATION,
                               
    &thread_id);
      
    if (thread_handle == NULL) {
        
    // perhaps STACK_SIZE_PARAM_IS_A_RESERVATION is not supported, try again
        
    // without the flag.
        thread_handle =
        (HANDLE)_beginthreadex(NULL,
                               (unsigned)stack_size,
                               (unsigned (__stdcall 
    *)(void*)) java_start,
                               thread,
                               CREATE_SUSPENDED,
                               
    &thread_id);
      }
      
    if (thread_handle == NULL) {
        
    // Need to clean up stuff we've allocated so far
        CloseHandle(osthread->interrupt_event());
        thread
    ->set_osthread(NULL);
        delete osthread;
        
    return NULL;
      }
      
      Atomic::inc_ptr((intptr_t
    *)&os::win32::_os_thread_count);

      
    // Store info on the Win32 thread into the OSThread
      osthread->set_thread_handle(thread_handle);
      osthread
    ->set_thread_id(thread_id);

      
    // Initial thread state is INITIALIZED, not SUSPENDED
      {
        MutexLockerEx ml(thread
    ->SR_lock(), Mutex::_no_safepoint_check_flag);
        osthread
    ->set_state(INITIALIZED);
      }

      
    // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
      return true;
    }

    可以看出,SUN JVM在Windows下的實現,使用_beginthreadex來創建線程,注釋中也說明了為什么不用“Window編程書籍推薦使用”的CreateThread函數。由此看出,Java線程在Window下的實現是使用內核線程。

    而在Linux下又是怎樣的呢?

    在os_linux.cpp文件中的代碼摘錄如下:

    # include <pthread.h>

    bool
     os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
      assert(thread
    ->osthread() == NULL, "caller responsible");

      
    // Allocate the OSThread object
      OSThread* osthread = new OSThread(NULL, NULL);
      
    if (osthread == NULL) {
        
    return false;
      }

      
    // set the correct thread state
      osthread->set_thread_type(thr_type);

      
    // Initial state is ALLOCATED but not INITIALIZED
      osthread->set_state(ALLOCATED);

      thread
    ->set_osthread(osthread);

      
    // init thread attributes
      pthread_attr_t attr;
      pthread_attr_init(
    &attr);
      pthread_attr_setdetachstate(
    &attr, PTHREAD_CREATE_DETACHED);

      
    // stack size
      if (os::Linux::supports_variable_stack_size()) {
        
    // calculate stack size if it's not specified by caller
        if (stack_size == 0) {
          stack_size 
    = os::Linux::default_stack_size(thr_type);

          
    switch (thr_type) {
          
    case os::java_thread:
            
    // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
            if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create();
            
    break;
          
    case os::compiler_thread:
            
    if (CompilerThreadStackSize > 0) {
              stack_size 
    = (size_t)(CompilerThreadStackSize * K);
              
    break;
            } 
    // else fall through:
              
    // use VMThreadStackSize if CompilerThreadStackSize is not defined
          case os::vm_thread: 
          
    case os::pgc_thread: 
          
    case os::cgc_thread: 
          
    case os::watcher_thread: 
            
    if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
            
    break;
          }
        }

        stack_size 
    = MAX2(stack_size, os::Linux::min_stack_allowed);
        pthread_attr_setstacksize(
    &attr, stack_size);
      } 
    else {
        
    // let pthread_create() pick the default value.
      }

      
    // glibc guard page
      pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));

      ThreadState state;

      {
        
    // Serialize thread creation if we are running with fixed stack LinuxThreads
        bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();
        
    if (lock) {
          os::Linux::createThread_lock()
    ->lock_without_safepoint_check();
        }

        pthread_t tid;
        
    int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

        pthread_attr_destroy(
    &attr);

        
    if (ret != 0) {
          
    if (PrintMiscellaneous && (Verbose || WizardMode)) {
            perror(
    "pthread_create()");
          }
          
    // Need to clean up stuff we've allocated so far
          thread->set_osthread(NULL);
          delete osthread;
          
    if (lock) os::Linux::createThread_lock()->unlock();
          
    return false;
        }

        
    // Store pthread info into the OSThread
        osthread->set_pthread_id(tid);

        
    // Wait until child thread is either initialized or aborted
        {
          Monitor
    * sync_with_child = osthread->startThread_lock();
          MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
          
    while ((state = osthread->get_state()) == ALLOCATED) {
            sync_with_child
    ->wait(Mutex::_no_safepoint_check_flag);
          }
        }

        
    if (lock) {
          os::Linux::createThread_lock()
    ->unlock();
        }
      }

      
    // Aborted due to thread limit being reached
      if (state == ZOMBIE) {
          thread
    ->set_osthread(NULL);
          delete osthread;
          
    return false;
      }

      
    // The thread is returned suspended (in state INITIALIZED),
      
    // and is started higher up in the call chain
      assert(state == INITIALIZED, "race condition");
      
    return true;
    }

    Java在Linux下的線程的創建,使用了pthread線程庫,而pthread就是一個用戶線程庫,因此結論是,Java在Linux下是使用用戶線程實現的。





    溫少 2007-04-18 05:28 發表評論
    posted @ 2007-04-18 05:28 溫少的日志 閱讀(945) | 評論 (4)編輯 收藏
     

    MessageDigest的選擇好多,包括MD2、MD4、MD5、SHA-1、SHA-256、RIPEMD128、RIPEMD160等等。我們如何選擇呢?

    選擇考慮在兩個方面:安全、速度。

    MD2很安全,但是速度極慢,一般不用。

    速度方面,最快的是MD4,MD5比SHA-1快

    速度排名:MD4 > MD5 > RIPEMD-128 > SHA-1 > REPEMD-160

    按照《應用密碼學手冊》提供的表格數據為:
    MD4 長度 128 相對速度 1
    MD5 長度 128 相對速度 0.68
    REPEMD-128 長度 128 相對速度 0.39
    SHA-1 長度 160 相對速度 0.29
    REPEMD-160 長度 160 相對速度 0.24

    我親自測試的結果和《應用密碼學手冊》提供的數據接近。

    MD4已經很早證明有缺陷,很少使用,最流行的是MD5和SHA-1,但MD5和SHA1也被王小云找到碰撞,證實不安全。

    傳說SHA-1比MD5要安全,但是SHA-1有美國國家安全局的背景,有人懷疑這個算法背后有不可告人的秘密,我也是陰謀論者之一,傾向選擇MD5而不是SHA-1。王小云找到SHA-1碰撞之后,可以說傳說的謠言破滅了,而且MD5速度要比SHA-1快差不多一倍,沒有什么理由選擇SHA-1。

    ----------------------------------

    在Java的現實環境中是怎樣?

    在SUN的JCE實現中,只提供了MD2、MD5、SHA-1,SHA-256等常用的MessageDigest算法。

    開源的JCE實現bouncycastle則提供了眾多的實現,包括MD整個系列,SHA整個系列,RIPEMD整個系列。

    很多的開源項目都帶一個bcprov-jdk14.jar的包,可以說bouncycastle應用很廣泛。SUN公司的一些項目也用了bouncycastle,例如JXTA。

    但實際上,SUN的實現包括了MD4,但你需要這樣使用:
    MessageDigest md = sun.security.provider.MD4.getInstance();


    但是,JDK帶實現性能要比bouncycastle性能好得多,相差速度通常超過一倍以上,我測試過MD5、SHA1和MD4,其性能差別都是類似,一倍多。

    比較的結論:
    bouncycastle開源免費,提供算法多,但速度較慢
    SUN JCE提供的實現,包括了流行常用算法,速度很快,同類型算法比bouncycastle要快一倍以上。

    ----------------------------------

    結論:

    又要安全又要速度,選擇MD5
    追求安全,不在意速度,相信傳說,不相信陰謀論,選擇SHA系列
    追求速度,安全次之,可以選擇MD4。

    ----------------------------------
    現實例子:
    emule采用MD4和SHA-1兩種結合使用
    apache之類的技術網站,提供下載的文件,同時提供一個校驗文件.md5



    溫少 2007-04-14 17:02 發表評論
    posted @ 2007-04-14 17:02 溫少的日志 閱讀(493) | 評論 (0)編輯 收藏
     
    JSR-000203 More New I/O APIs for the Java Platform - Early Draft Review

    http://jcp.org/aboutJava/communityprocess/edr/jsr203/index.html


    API的Early Draft Review出來了,就意味很快就要真的出來啦!!

    以下是其文檔的一個Sample

     static class IOTransaction {
          
    public ByteBuffer buffer() {  }
          
    public long position() {  }
          
    public long updatePosition(int transferred) {  }
      }

      
    static class WriteHandler implements CompletionHandler<Integer> {

          
    public WriteHandler(AsynchronousFileChannel ch) {  }

          
    private AsynchronousFileChannel channel() {  }

          
    public void completed(IoFuture<Integer> result) {
              
    int bytesTransferred;
              
    try {
                  bytesTransferred 
    = result.getNow();
              } 
    catch (ExecutionException x) {  }
     
              IOTransaction transaction 
    = (IOTransaction)result.attachment();   
              ByteBuffer buffer 
    = transaction.buffer();
              
    if (buffer.remaining() > 0) {
                  
    long position = transaction.updatePosition(bytesTransferred);
                  channel().write(buffer, position, transaction, 
    this);
              }
          }
      }

      FileReference file 
    = 
      List
    <IOTransaction> transactionList = 
      
      AsynchronousFileChannel ch 
    = AsynchronousFileChannel.open(file, OpenFlag.WRITE);

      WriteHandler handler 
    = new WriteHandler(ch);

      
    for (IOTransaction transaction: transactionList) {
          
    // use the transaction as the attachment
          ch.write(transaction.buffer(), transaction.position(), transaction, handler);
      }


    就是我最近很需要的東西,一個異步I/O的實現,十分期待中!!



    溫少 2007-04-14 12:15 發表評論
    posted @ 2007-04-14 12:15 溫少的日志 閱讀(265) | 評論 (0)編輯 收藏
     

    不是使用每連接一線程的技術,而是使用多路復用技術。

    作了一個分配算法。第一個HTTP Request返回取得ContentLength之后,如果使用多個連接下載,則需要一個分配算法,分配每個Request所對應的Range。分配的部分可能是一個連續的塊,例如bytes=100-999,也可能是一些碎塊,例如bytes=500-600,700-800,850-999。為此,我做了一個數據結構,其提供的功能類似java.util.BitSet,也支持and、or等操作。

    實現了對ContentType為multipart/bytes的HTTP Message Body的解釋。如果發送HTTP Request,Range為多個不連續的部分,返回的HTTP Message,就會是multipart,每個part都會包括一個Head和一個Body,需要一個解析器。

    下一步就是把HTTP下載加入P2P下載中!


    溫少 2007-04-12 01:37 發表評論
    posted @ 2007-04-12 01:37 溫少的日志 閱讀(381) | 評論 (0)編輯 收藏
     

    最近編碼更流暢了。原因包括:

    1) 絕大多數時候純鍵盤操作,Eclipse 200多個快捷鍵,我熟練使用絕大部分,編碼的過程,如同行云流水般。

    2)掌握了更多的解決問題的辦法,有了更廣的知識面,編碼時,信手拈來。最近一年里,掌握了很多知識,包括并發、網絡、操作系統等等方面的知識。

    3)組織代碼的能力更強了,最近對于大型復雜的程序,組織代碼的能力更強了,組織程序的能力包括,更好的結構,更好的擴展性,可測試性,可管理性等等。
      a) 在編碼的過程中,使得更多的模塊可以單獨于整個環境獨立測試
      b) 精心處理過的LOG,使得代碼更容易跟蹤,排錯。
      c) 復雜的模塊,附帶監控管理界面,使得排錯和優化都更為方便。
      d) 使用制作狀態轉換表的手段,清晰化復雜的狀態處理。在前些年設計/實現工作流引擎時,就開始使用狀態轉換表描述狀態機,但現在面臨的狀態機復雜。




    溫少 2007-03-31 02:42 發表評論
    posted @ 2007-03-31 02:42 溫少的日志 閱讀(262) | 評論 (0)編輯 收藏
     

    貼圖的實現方式為:

    1、把剪切板中的圖片存在本地的SendingImages目錄,存放的格式使用PNG,當然可以其他格式,但是PNG格式更小。
    2、使用MD5算法產生一個ImageID。當然可以使用SHA1等其他算法
    3、把imageID發送remote peer
    4、當remote peer收到imageID時,檢查本地ReceivedImage目錄,如果已經存在,顯示圖片,不存在則發送一個RequestImage請求,并在聊天記錄中顯示一個等待信息(為一個GIF動畫)。
    5、本地Peer收到RequestImage請求之后,發送圖片數據。如果圖片大于64K,則分塊發送。
    6、remote peer收到圖像數據之后,進行校驗,看是否正確。
    7、校驗通過后,把圖片在聊天面板上顯示(替換等待圖片)


    預定義表情的實現很簡單,自定義表情的實現和貼圖實現一致,只是少了從剪貼板保存圖片的過程。



    溫少 2007-03-30 22:01 發表評論
    posted @ 2007-03-30 22:01 溫少的日志 閱讀(228) | 評論 (0)編輯 收藏
     
    上一篇博客寫了我一些關于P2P下載以及平臺的思考,有這樣的思考,是因為我正在做一件這樣的事情。

    我介紹一下我正在做的事情吧:

    1、基于JXTA,我崇拜Bill Joy,學習JXTA就是因為我崇拜他,之后覺得這個技術很棒。但是JXTA存在一些用戶不友好的地方,包括JXTA的ConfigDialog和DialogAuthenticator是十分用戶不友好的,我重寫了這些部分。雖然是一些無關痛癢的地方,但是可以改變用戶體驗,提高用戶友好性。

    2、簡單的插件機制,我做了一個簡單的插件系統,Application啟動之后挨個裝載服務,UI也是服務之一,UI也是基于插件的,在微內核框架流行的今天,使用一個簡單的插件機制似乎不是太好,等過一段時間之后考慮使用osgi替代之。

    3、提供了兩個功能,聊天和文件共享下載。這兩個功能分別表現為兩個JXTA的Service。

    4、聊天功能。目前還比較簡單,只實現了不帶格式的文本聊天,但是我隨后會加入帶格式的文本聊天,也將會加入類似騰訊QQ那樣的貼圖支持,自定義表情支持,騰訊QQ的實現很巧妙,但并不困難。四月初的版本就有可能實現之。

    5、共享和下載。目前實現了文件和文件夾的共享。其中包括了高級智能錯誤檢測(AICH)等。傳輸協議參考了BT和emule的協議。在界面中還實現對DragAndDrop支持,從Windows Explore中拖一個文件到目錄共享的面板,即開始共享該文件。

    6、存儲信息采用apache的Derby數據庫。我很喜歡Berkeley DB,Berkely DB高效簡潔,但是License不開放。我最終還是采用Derby了,采用Derby將會帶來一系列好處,SQL支持、JDBC支持等等,License無限制等等。擴展的應用基于其上也十分方便。由于我曾經開發過多數據庫支持引擎KSQL,在KSQL上增加支持Derby的翻譯是很容易的事情。如此一來,可能存儲引擎部分,將有可能擴展到KSQL目前所支持的多種數據庫,包括嚴格測試過的Oracle、DB2、MS SQL Server,還有經過簡單測試支持Sybase、PostgreSQL、MySQL。

    7、最近的JXTA Java SE 2.5版本,使用了nio來管理連接,也就說,使用了多路復用的技術,使得每個Peer創建大量連接成為可能,例如Windows下默認最大的多路復用支持1024個連接。而Linux下,java nio是使用epoll實現的,并發性能將更好,這對于聚合點來說很重要。普通的Peer部署在Linux下可能較少,但是聚合點部署在Linux完全是可能的。

    8、使用Swing做界面,使用Java 6 SE的Swing,做了系統托盤Tray的支持等等。由于Swing的UI設計工具很不穩定,最終完全手工編寫UI部分代碼,雖然辛苦,但是代碼簡潔,不同UI Designer生成的那樣。

    9、我期望4月初發布一個版本,提供一個基本可用的版本。

    10、我是從1月初開始學習JXTA的,到現在還不滿3個月,其中還包括過年回家休息等等,玩游戲沉迷等等,但總的來說,我對這個學習速度很滿意。不過其中感覺最爽的是,在這個過程中,編碼時,基本純鍵盤操作,不用鼠標,如行云流水一邊,十分流暢,工作效率高,人也舒服。




    溫少 2007-03-25 06:39 發表評論
    posted @ 2007-03-25 06:39 溫少的日志 閱讀(268) | 評論 (0)編輯 收藏
    僅列出標題
    共8頁: 上一頁 1 2 3 4 5 6 7 8 下一頁 
     
    主站蜘蛛池模板: 狼群影院在线观看免费观看直播| 中国一级全黄的免费观看| 久视频精品免费观看99| 无码乱人伦一区二区亚洲 | 亚洲精品美女久久久久久久| 两个人的视频高清在线观看免费| 亚洲一线产区二线产区精华| 国产一卡2卡3卡4卡无卡免费视频| 亚洲不卡视频在线观看| 一个人免费高清在线观看| 亚洲国产日韩在线成人蜜芽| 成人免费AA片在线观看| 国产成人精品日本亚洲直接| 永久久久免费浮力影院| 一个人看的免费视频www在线高清动漫| 亚洲国产精品一区二区第一页免| 男女一进一出抽搐免费视频 | 亚洲第一福利视频| 2021久久精品免费观看| 亚洲AV成人片无码网站| vvvv99日韩精品亚洲| a级精品九九九大片免费看 | MM1313亚洲国产精品| 亚洲男人在线无码视频| 波多野结衣免费一区视频| 亚洲熟妇无码久久精品| 国产成人免费网站在线观看| 九九99热免费最新版| 亚洲激情电影在线| 亚洲av无码国产精品色在线看不卡 | 黄网站色视频免费在线观看的a站最新| 亚洲国产一区在线| 国产精品免费一级在线观看| 美女巨胸喷奶水视频www免费| 亚洲精品视频在线播放| 全黄性性激高免费视频| 久久久高清日本道免费观看| 亚洲综合色婷婷在线观看| 久久精品国产亚洲7777| 久久经典免费视频| 中国内地毛片免费高清|