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

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

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

    byterat

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      54 隨筆 :: 0 文章 :: 15 評論 :: 0 Trackbacks

    #

    這些東西都是Java Script大部分都是由老外寫的,并且封裝得很好,在運用上也很方便,而且也都兼容FF與OPERA,檔案中少部分是由中國的高手寫的。

     

      一、多樣化摺疊菜單:下載

      一個由老外寫的折疊式垂直菜單,多樣化,多功能,可自訂,使用容易,支持FF。

    國內外 Java Script 經典封裝
    圖1

      二、CSS圓角邊框:下載

      以CSS為主要,用Java Script封裝的相當完整,也是老外寫的,支持多瀏覽器,可以自訂樣式,目前有十多種可以運用。

    國內外 Java Script 經典封裝
    圖2

    國內外 Java Script 經典封裝
    圖3

      三、模擬視窗:下載

      用層模擬的視窗,是一個中國高手寫的,Java Script封裝的相當好,使用上也很容易

    國內外 Java Script 經典封裝
    圖4
      

      四、支持FF的省略符:下載

      說到省略符,那非CSS莫屬,有個老外用Java Script來實現,并且是批量處理的,重點是支持FF。

    國內外 Java Script 經典封裝
    圖5

      五、TAB選項卡:下載

      用Java Script模仿各種作業系統的選項卡,老外就是牛,不僅支援多樣式的即時切換,同時也支援每個選項卡是否附帶圖示的切換選項,選項卡也可以上下切換。

    國內外 Java Script 經典封裝
    圖6
      

      六、最佳化多樣式Windows:下載

      用層模擬視窗的最佳代表作,這是我看過功能最多的模擬式窗,內附多達74項功能與樣式,你完完全全可以把它當成是一個真正的視窗來應用,可以根據你的需求來應用,快丟掉你那認為好用的層視窗,這套封裝非常完整的視窗絕對可以滿足你的各種需求。

    國內外 Java Script 經典封裝
    圖7

    國內外 Java Script 經典封裝
    圖8

      七、多樣化的垂直菜單:附件

      別具風格的方塊式垂直折疊菜單,目前有8種風格可以運用,如果你已經厭煩WEB上平凡的菜單,這套在國外頗受歡迎的菜單肯定是你的最佳首選。

    國內外 Java Script 經典封裝
    圖9
      

      八、多樣化的連結提示效果:下載

      這個連結提示樣式允許你直接寫入css與html,共有14項功能可以讓你自訂。

    國內外 Java Script 經典封裝
    圖10

      九、側欄式折疊菜單:下載

      這是一個側欄式的折疊菜單,它允許你設置它是否有過渡效果、側欄菜單是否自動伸縮、菜單項切換是否允許動畫過渡、是否輪替切換等多項設置,并且也有多種樣式可以運用。

      這個腳本有個很好玩的東東,下載并且解壓後,請進入samples的目錄并打show.html看看效果,我不知道這效果容不容易實現,但是這效果很牛,菜單全自動運行的~

    國內外 Java Script 經典封裝
    圖11
      

      十、圖形滾動條:下載

      老外寫的圖形滾動條,有多種樣式,在ie里頭還支持滾輪滾動。

    國內外 Java Script 經典封裝
    圖12

      十一、圖片倒影效果:下載
      說到圖片倒影,不外乎就是直接作成圖片跟css濾鏡來實現,但是這個是用Java Script實現的,值得借鏡。

    國內外 Java Script 經典封裝
    圖13

      十二、代碼自動高亮:下載

      雖說這不是什麼新東西,但總是會有人需要吧,而且想學正則表達的人,這肯定是最佳借鏡的作品。

    國內外 Java Script 經典封裝
    圖14
      
      

      十三、酷似flash效果的圖片展示:下載

      這個老外牛到有點變態,這圖片展示效果已經跟FLASH沒什麼兩樣,用Java Script寫的耶。

    國內外 Java Script 經典封裝
    圖15

      十四、讓ie6支援png圖檔:下載

    國內外 Java Script 經典封裝
    圖16

      這個問題之前被很多人討論過,我就不多說什麼了,有需要下吧。

    posted @ 2007-12-13 17:29 比特鼠 閱讀(5341) | 評論 (5)編輯 收藏

    在一個老外的Blog上看到了這個網站,發現原來是一個以C語言為基準的性能比較網站!

    Java還算不錯,Ruby就不怎么樣了, 在腳本語言中居然排在了最后!

    看來,解析性的語言玩起來是簡單方便了,可是卻是以損失性能為代價的!
    posted @ 2007-12-13 16:34 比特鼠 閱讀(468) | 評論 (0)編輯 收藏

    BIG-ENDIAN(大字節序、高字節序)
    LITTLE-ENDIAN(小字節序、低字節序)
    主機字節序
    網絡字節順序
    JAVA字節序

    1.BIG-ENDIAN、LITTLE-ENDIAN跟多字節類型的數據有關的比如int,short,long型,而對單字節數據byte卻沒有影響。BIG-ENDIAN就是低位字節排放在內存的低端,高位字節排放在內存的高端。而LITTLE-ENDIAN正好相反。
    比如 int a = 0x05060708
    在BIG-ENDIAN的情況下存放為:
    字節號 0 1 2 3
    數據 05 06 07 08
    在LITTLE-ENDIAN的情況下存放為:
    字節號 0 1 2 3
    數據 08 07 06 05

    2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關的,每一種CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架構的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器。這其實就是所謂的主機字節序。而網絡字節序是指數據在網絡上傳輸時是大頭還是小頭的,在Internet的網絡字節序是BIG-ENDIAN。所謂的JAVA字節序指的是在JAVA虛擬機中多字節類型數據的存放順序,JAVA字節序也是BIG-ENDIAN。

    3.所以在用C/C++寫通信程序時,在發送數據前務必用htonl和htons去把整型和短整型的數據進行從主機字節序到網絡字節序的轉換,而接收數據后對于整型和短整型數據則必須調用ntohl和ntohs實現從網絡字節序到主機字節序的轉換。如果通信的一方是JAVA程序、一方是C/C++程序時,則需要在C/C++一側使用以上幾個方法進行字節序的轉換,而JAVA一側,則不需要做任何處理,因為JAVA字節序與網絡字節序都是BIG-ENDIAN,只要C/C++一側能正確進行轉換即可(發送前從主機序到網絡序,接收時反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節序的問題了。

    4.如果網絡上全部是PowerPC,SPARC和Motorola CPU的主機那么不會出現任何問題,但由于實際存在大量的IA架構的CPU,所以經常出現數據傳輸錯誤。

    5.文章開頭所提出的問題,就是因為程序運行在X86架構的PC SERVER上,發送數據的一端用C實現的,接收一端是用JAVA實現的,而發送端在發送數據前未進行從主機字節序到網絡字節序的轉換,這樣接收端接收到的是LITTLE-ENDIAN的數據,數據解釋自然出錯。
    具體數據如下,實際發送的數據為23578
    發送端發送數據: 1A 5C
    接收端接收到數據后,按BIG-ENDIAN進行解釋具體數據是多少?你們自己去計算并比較吧!


    ===============================================================================================

    Big Endian and Little Endian

        談到字節序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存儲數據,而x86系列則采用little endian方式存儲數據。那么究竟什么是big endian,什么又是little endian呢?

        其實big endian是指低地址存放最高有效字節(MSB),而little endian則是低地址存放最低有效字節(LSB),即常說的低位在先,高位在后。
        用文字說明可能比較抽象,下面用圖像加以說明。比如數字0x12345678在兩種不同字節序CPU中的存儲順序如下所示:

    Big Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     12     |      34    |     56      |     78    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Little Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     78     |      56    |     34      |     12    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

        從上面兩圖可以看出,采用big endian方式存儲數據是符合我們人類的思維習慣的。而little endian,!@#$%^&*,見鬼去吧 -_-|||

        為什么要注意字節序的問題呢?你可能這么問。當然,如果你寫的程序只在單機環境下面運行,并且不和別人的程序打交道,那么你完全可以忽略字節序的存在。但是,如果你的程序要跟別人的程序產生交互呢?尤其是當你把你在微機上運算的結果運用到計算機群上去的話。在這里我想說說兩種語言。C/C++語言編寫的程序里數據存儲順序是跟編譯平臺所在的CPU相關的,而JAVA編寫的程序則唯一采用big endian方式來存儲數據。試想,如果你用C/C++語言在x86平臺下編寫的程序跟別人的JAVA程序互通時會產生什么結果?就拿上面的 0x12345678來說,你的程序傳遞給別人的一個數據,將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取big endian方式存儲數據,很自然的它會將你的數據翻譯為0x78563412。什么?竟然變成另外一個數字了?是的,就是這種后果。因此,在你的C程序傳給JAVA程序之前有必要進行字節序的轉換工作。

        無獨有偶,所有網絡協議也都是采用big endian的方式來傳輸數據的。所以有時我們也會把big endian方式稱之為網絡字節序。當兩臺采用不同字節序的主機通信時,在發送數據之前都必須經過字節序的轉換成為網絡字節序后再進行傳輸。ANSI C中提供了四個轉換字節序的宏。


    ========================================================================================================

    /**
    * 通信格式轉換
    *
    * Java和一些windows編程語言如c、c++、delphi所寫的網絡程序進行通訊時,需要進行相應的轉換
    * 高、低字節之間的轉換
    * windows的字節序為低字節開頭
    * linux,unix的字節序為高字節開頭
    * java則無論平臺變化,都是高字節開頭
    */

    public class FormatTransfer {
    /**
      * 將int轉為低字節在前,高字節在后的byte數組
      * @param n int
      * @return byte[]
      */
    public static byte[] toLH(int n) {
      byte[] b = new byte[4];
      b[0] = (byte) (n & 0xff);
      b[1] = (byte) (n >> 8 & 0xff);
      b[2] = (byte) (n >> 16 & 0xff);
      b[3] = (byte) (n >> 24 & 0xff);
      return b;
    }

    /**
      * 將int轉為高字節在前,低字節在后的byte數組
      * @param n int
      * @return byte[]
      */
    public static byte[] toHH(int n) {
      byte[] b = new byte[4];
      b[3] = (byte) (n & 0xff);
      b[2] = (byte) (n >> 8 & 0xff);
      b[1] = (byte) (n >> 16 & 0xff);
      b[0] = (byte) (n >> 24 & 0xff);
      return b;
    }

    /**
      * 將short轉為低字節在前,高字節在后的byte數組
      * @param n short
      * @return byte[]
      */
    public static byte[] toLH(short n) {
      byte[] b = new byte[2];
      b[0] = (byte) (n & 0xff);
      b[1] = (byte) (n >> 8 & 0xff);
      return b;
    }

    /**
      * 將short轉為高字節在前,低字節在后的byte數組
      * @param n short
      * @return byte[]
      */
    public static byte[] toHH(short n) {
      byte[] b = new byte[2];
      b[1] = (byte) (n & 0xff);
      b[0] = (byte) (n >> 8 & 0xff);
      return b;
    }

     

    /**
      * 將將int轉為高字節在前,低字節在后的byte數組

    public static byte[] toHH(int number) {
      int temp = number;
      byte[] b = new byte[4];
      for (int i = b.length - 1; i > -1; i--) {
        b = new Integer(temp & 0xff).byteValue();
        temp = temp >> 8;
      }
      return b;
    }

    public static byte[] IntToByteArray(int i) {
        byte[] abyte0 = new byte[4];
        abyte0[3] = (byte) (0xff & i);
        abyte0[2] = (byte) ((0xff00 & i) >> 8);
        abyte0[1] = (byte) ((0xff0000 & i) >> 16);
        abyte0[0] = (byte) ((0xff000000 & i) >> 24);
        return abyte0;
    }


    */

    /**
      * 將float轉為低字節在前,高字節在后的byte數組
      */
    public static byte[] toLH(float f) {
      return toLH(Float.floatToRawIntBits(f));
    }

    /**
      * 將float轉為高字節在前,低字節在后的byte數組
      */
    public static byte[] toHH(float f) {
      return toHH(Float.floatToRawIntBits(f));
    }

    /**
      * 將String轉為byte數組
      */
    public static byte[] stringToBytes(String s, int length) {
      while (s.getBytes().length < length) {
        s += " ";
      }
      return s.getBytes();
    }


    /**
      * 將字節數組轉換為String
      * @param b byte[]
      * @return String
      */
    public static String bytesToString(byte[] b) {
      StringBuffer result = new StringBuffer("");
      int length = b.length;
      for (int i=0; i<length; i++) {
        result.append((char)(b & 0xff));
      }
      return result.toString();
    }

    /**
      * 將字符串轉換為byte數組
      * @param s String
      * @return byte[]
      */
    public static byte[] stringToBytes(String s) {
      return s.getBytes();
    }

    /**
      * 將高字節數組轉換為int
      * @param b byte[]
      * @return int
      */
    public static int hBytesToInt(byte[] b) {
      int s = 0;
      for (int i = 0; i < 3; i++) {
        if (b >= 0) {
        s = s + b;
        } else {
        s = s + 256 + b;
        }
        s = s * 256;
      }
      if (b[3] >= 0) {
        s = s + b[3];
      } else {
        s = s + 256 + b[3];
      }
      return s;
    }

    /**
      * 將低字節數組轉換為int
      * @param b byte[]
      * @return int
      */
    public static int lBytesToInt(byte[] b) {
      int s = 0;
      for (int i = 0; i < 3; i++) {
        if (b[3-i] >= 0) {
        s = s + b[3-i];
        } else {
        s = s + 256 + b[3-i];
        }
        s = s * 256;
      }
      if (b[0] >= 0) {
        s = s + b[0];
      } else {
        s = s + 256 + b[0];
      }
      return s;
    }


    /**
      * 高字節數組到short的轉換
      * @param b byte[]
      * @return short
      */
    public static short hBytesToShort(byte[] b) {
      int s = 0;
      if (b[0] >= 0) {
        s = s + b[0];
        } else {
        s = s + 256 + b[0];
        }
        s = s * 256;
      if (b[1] >= 0) {
        s = s + b[1];
      } else {
        s = s + 256 + b[1];
      }
      short result = (short)s;
      return result;
    }

    /**
      * 低字節數組到short的轉換
      * @param b byte[]
      * @return short
      */
    public static short lBytesToShort(byte[] b) {
      int s = 0;
      if (b[1] >= 0) {
        s = s + b[1];
        } else {
        s = s + 256 + b[1];
        }
        s = s * 256;
      if (b[0] >= 0) {
        s = s + b[0];
      } else {
        s = s + 256 + b[0];
      }
      short result = (short)s;
      return result;
    }

    /**
      * 高字節數組轉換為float
      * @param b byte[]
      * @return float
      */
    public static float hBytesToFloat(byte[] b) {
      int i = 0;
      Float F = new Float(0.0);
      i = ((((b[0]&0xff)<<8 | (b[1]&0xff))<<8) | (b[2]&0xff))<<8 | (b[3]&0xff);
      return F.intBitsToFloat(i);
    }

    /**
      * 低字節數組轉換為float
      * @param b byte[]
      * @return float
      */
    public static float lBytesToFloat(byte[] b) {
      int i = 0;
      Float F = new Float(0.0);
      i = ((((b[3]&0xff)<<8 | (b[2]&0xff))<<8) | (b[1]&0xff))<<8 | (b[0]&0xff);
      return F.intBitsToFloat(i);
    }

    /**
      * 將byte數組中的元素倒序排列
      */
    public static byte[] bytesReverseOrder(byte[] b) {
      int length = b.length;
      byte[] result = new byte[length];
      for(int i=0; i<length; i++) {
        result[length-i-1] = b;
      }
      return result;
    }

    /**
      * 打印byte數組
      */
    public static void printBytes(byte[] bb) {
      int length = bb.length;
      for (int i=0; i<length; i++) {
        System.out.print(bb + " ");
      }
      System.out.println("");
    }

    public static void logBytes(byte[] bb) {
      int length = bb.length;
      String ut = "";
      for (int i=0; i<length; i++) {
        ut = out + bb + " ";
      }

    }

    /**
      * 將int類型的值轉換為字節序顛倒過來對應的int值
      * @param i int
      * @return int
      */
    public static int reverseInt(int i) {
      int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
      return result;
    }

    /**
      * 將short類型的值轉換為字節序顛倒過來對應的short值
      * @param s short
      * @return short
      */
    public static short reverseShort(short s) {
      short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
      return result;
    }

    /**
      * 將float類型的值轉換為字節序顛倒過來對應的float值
      * @param f float
      * @return float
      */
    public static float reverseFloat(float f) {
      float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
      return result;
    }

    }

    posted @ 2007-10-24 09:57 比特鼠 閱讀(3406) | 評論 (0)編輯 收藏

    實現Leader/Fellows模式的項目--CAJ, 地址是:http://caj.cosylab.com/
    posted @ 2007-10-23 14:57 比特鼠 閱讀(198) | 評論 (0)編輯 收藏

    網址:http://httpd.apache.org/docs/2.0/programs/ab.html
    posted @ 2007-10-23 14:53 比特鼠 閱讀(273) | 評論 (0)編輯 收藏

    緩沖區基礎

    抽象類Buffer是java.nio包支持緩沖區的基礎。 Buffer 的工作方式就象內存中用于讀寫基本數據類型的 RandomAccessFile 。象 RandomAccessFile 一樣,使用 Buffer ,所執行的下一個操作(讀/寫)在當前某個位置發生。執行讀/寫操作中的任一個都會改變那個位置,所以在寫操作之后進行讀操作不會讀到剛才所寫的內容,而會讀到剛才所寫內容之后的數據。 Buffer 提供了四個指示方法,用于訪問線性結構(從最高值到最低值):

    capacity() :表明緩沖區的容量大小, 一旦確定了大小, 將不能再改變;
    limit() :告訴您到目前為止已經往緩沖區填了多少字節,或者讓您用 :limit(int newLimit) 來改變這個限制
    position() :告訴您當前的位置,以執行下一個讀/寫操作
    mark() :為了稍后用 reset() 進行重新設置而記住某個位置
    flip() :交換限制指針和位置指針,然后將位置置為 0,并廢棄已經做的mark標記

    緩沖區的基本操作是讀 get() 和寫 put() ;然而,這些方法在子類中都是針對每種數據類型的特定方法。為了說明這一情況,讓我們研究一個簡單示例,該示例演示了從同一個緩沖區讀和寫一個字符。在清單 1 中, flip() 方法交換限制和位置,然后將位置置為 0,并廢棄標記,讓您讀剛才所寫的數據:


    清單 1. 讀/寫示例
    import java.nio.*;
    ...
    CharBuffer buff = ...;
    buff.put('A');
    buff.flip();
    char c = buff.get();
    System.out.println("An A: " + c);
     


    現在讓我們研究一些具體的 Buffer 子類。

     

    緩沖區類型

    Merlin 具有 7 種特定的 Buffer 類型,每種類型對應著一個基本數據類型(不包括 boolean):

    ByteBuffer       //存放任何除boolean類型外的其他基本類型
    CharBuffer       //存放char
    DoubleBuffer     //存放double
    FloatBuffer      //存放float
    IntBuffer        //存放int
    LongBuffer       //存放long
    ShortBuffer      //存放short

    在本文后面,我將討論第 8 種類型 MappedByteBuffer ,它用于內存映射文件。如果您必須使用的類型不是這些基本類型,則可以先從 ByteBuffer 獲得字節類型,然后將其轉換成 Object 或其它任何類型。


    創建緩沖區
    一共有兩種類型的緩沖區,直接緩沖區和非直接緩沖區。

    在創建緩沖區時,可以要求創建直接緩沖區,創建直接緩沖區的成本要比創建間接緩沖區高,但這可以使運行時環境直接在該緩沖區上進行較快的本機 I/O 操作。因為創建直接緩沖區所增加的成本,所以直接緩沖區只用于長生存期的緩沖區,而不用于短生存期、一次性且用完就丟棄的緩沖區。而且,只能在 ByteBuffer 這個級別上創建直接緩沖區,如果希望使用其它類型,則必須將 Buffer 轉換成更具體的類型。

    判斷一個緩沖區是否是直接緩沖區,可以調用isDirect()方法。

    有三種方式來獲取一個緩沖區的對象:
    a. 調用allocate()或者allocateDirect()方法直接分配,其中allocateDirect()返回的是直接緩沖區。
    b. 包裝一個數組,如:
          byte[] b = new byte[1024];
          ByteBuffer bb = ByteBuffer.wrap(b);
    c. 內存映射,即調用FileChannel的map()方法。

    緩沖區基本屬性
    這幾個屬性是每個緩沖區都有的并且是常用的操作。
    a. 容量(capacity),緩沖區大小
    b. 限制(limit),第一個不應被讀取或寫入的字節的索引,總是小于容量。
    c. 位置(position),下一個被讀取或寫入的字節的索引,總是小于限制。
    d. clear()方法:設置limit為capacity,position為0。
    e. filp()方法:設置limit為當前position,然后設置position為0。
    f. rewind()方法:保持limit不變,設置position為0。

    緩沖區數據操作
    操作包括了讀取和寫入數據兩種。
    讀取數據使用get()及其系列方法,除boolean外,每一種類型包括了對應的get()方法,如getInt(),getChar()等,get()方法用來讀取字節,支持相對和絕對索引兩種方式。
    寫入數據使用put()及其系列方法,和get()方法是對應的。

    package nio;

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;

    public class BufferDemo ...{

        
        public static void main(String[] args) throws Exception...{
            //分配一個非直接緩沖區
            ByteBuffer bb = ByteBuffer.allocate(100);
            //向緩沖區寫入0到100的字節制
            for(int i = 0; i <100; i++)...{
                byte b = (byte) (Math.random() * 100);
                bb.put(b);
            }
            
            System.out.println("寫入文件前的緩沖區數據");
            bb.flip();
            while(bb.hasRemaining())
                System.out.print(bb.get() + " ");
            System.out.println();
            
            //獲取一個關聯到文件buffer.txt的信道
            FileChannel fc = new FileOutputStream("buffer.txt").getChannel();
            //將緩沖區數據寫到文件中
            bb.flip();
            fc.write(bb);
            //防止緩存
            fc.force(true);
            //關閉信道
            fc.close();
            bb = null;
            fc = null;
            
            //下面從文件中讀取數據
            fc = new FileInputStream("buffer.txt").getChannel();
            ByteBuffer bb2 = ByteBuffer.allocate((int) fc.size());
            fc.read(bb2);
            System.out.println("從文件讀取的緩沖區數據");
            bb2.flip();
            while(bb2.hasRemaining())
                System.out.print(bb2.get() + " ");
            System.out.println();
            fc.close();
            bb2 = null;
            fc = null;
            

        }

    }

    內存映射文件

    第 8 種 Buffer 類型 MappedByteBuffer 只是一種特殊的 ByteBuffer 。 MappedByteBuffer 將文件所在區域直接映射到內存。通常,該區域包含整個文件,但也可以只映射部分文件。所以,必須指定要映射文件的哪部分。而且,與其它 Buffer 對象一樣,這里沒有構造函數;必須讓 java.nio.channels.FileChannel 的 map() 方法來獲取 MappedByteBuffer 。此外,無需過多涉及通道就可以用 getChannel() 方法從 FileInputStream 或 FileOutputStream 獲取 FileChannel 。通過從命令行傳入文件名來讀取文本文件的內容,清單 4 顯示了 MappedByteBuffer :


    清單 4. 讀取內存映射文本文件
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.charset.*;
    public class ReadFileBuff {
      public static void main(String args[]) throws IOException {
         if (args.length != 0) {
          String filename = args[0];
          FileInputStream fis = new FileInputStream(filename);
          FileChannel channel = fis.getChannel();
          int length = (int)channel.size();
          MappedByteBuffer byteBuffer =
            channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
          Charset charset = Charset.forName("ISO-8859-1");
          CharsetDecoder decoder = charset.newDecoder();
          CharBuffer charBuffer = decoder.decode(byteBuffer);
          for (int i=0, n=charBuffer.length(); i<n; i++) {
            System.out.print(charBuffer.get());
          }
        }
      }
    }

    posted @ 2007-08-01 11:13 比特鼠 閱讀(3826) | 評論 (0)編輯 收藏

    1. 左移操作: x << n
      x可以是byte, short, char, int, long基本類型, n(位移量)只能是int型

      編譯器的執行步驟:
      1) 如果x是byte, short, char類型, 則將x提升為int;
      2) 如果x是byte, short, char, int類型, 則n被重新賦值(過程是:取n的補碼的低5位再轉成十進制的int值,相當對n取32模: n=n%32);
         如果x是long型, 則n被重新賦值(過程是:取n的補碼的低6位再轉成十進制的int值,相當對n取64模: n=n%64);
         (因為int類型為4個字節,即32位,移動32位將沒有任何意義.對于long則是模64)
      3) 對x左移n個位數, 整個表達式產生一個新值(x的值不變);
    2. <<是左移符號,列x<<1,就是x的內容左移一位(x的內容并不改變)
    3. >>是帶符號位的右移符號,x>>1就是x的內容右移一位,如果開頭是1則補1,是0責補0,(x的內容并不改變).
    4. >>>是不帶符號位的右移,x>>>1就是x的內容右移一位,開頭補0(x的內容并不改變)
    posted @ 2007-08-01 10:12 比特鼠 閱讀(2804) | 評論 (0)編輯 收藏

    原文地址 http://www.programbbs.com/doc/2433.htm
    為什么會排隊等待?

    下面的這個簡單的 Java 程序完成四項不相關的任務。這樣的程序有單個控制線程,控制在這四個任務之間線性地移動。此外,因為所需的資源 — 打印機、磁盤、數據庫和顯示屏 -- 由于硬件和軟件的限制都有內在的潛伏時間,所以每項任務都包含明顯的等待時間。因此,程序在訪問數據庫之前必須等待打印機完成打印文件的任務,等等。如果您正在等待程序的完成,則這是對計算資源和您的時間的一種拙劣使用。改進此程序的一種方法是使它成為多線程的。
     
    四項不相關的任務
     

    class myclass {
        static public void main(String args[]) {
            print_a_file();
            manipulate_another_file();
            access_database();
            draw_picture_on_screen();
        }
    }

    在本例中,每項任務在開始之前必須等待前一項任務完成,即使所涉及的任務毫不相關也是這樣。但是,在現實生活中,我們經常使用多線程模型。我們在處理某些任務的同時也可以讓孩子、配偶和父母完成別的任務。例如,我在寫信的同時可能打發我的兒子去郵局買郵票。用軟件術語來說,這稱為多個控制(或執行)線程。

    可以用兩種不同的方法來獲得多個控制線程:

    多個進程
    在大多數操作系統中都可以創建多個進程。當一個程序啟動時,它可以為即將開始的每項任務創建一個進程,并允許它們同時運行。當一個程序因等待網絡訪問或用戶輸入而被阻塞時,另一個程序還可以運行,這樣就增加了資源利用率。但是,按照這種方式創建每個進程要付出一定的代價:設置一個進程要占用相當一部分處理器時間和內存資源。而且,大多數操作系統不允許進程訪問其他進程的內存空間。因此,進程間的通信很不方便,并且也不會將它自己提供給容易的編程模型。


    線程
    線程也稱為輕型進程 (LWP)。因為線程只能在單個進程的作用域內活動,所以創建線程比創建進程要廉價得多。這樣,因為線程允許協作和數據交換,并且在計算資源方面非常廉價,所以線程比進程更可取。線程需要操作系統的支持,因此不是所有的機器都提供線程。Java 編程語言,作為相當新的一種語言,已將線程支持與語言本身合為一體,這樣就對線程提供了強健的支持。


    使用 Java 編程語言實現線程
    Java 編程語言使多線程如此簡單有效,以致于某些程序員說它實際上是自然的。盡管在 Java 中使用線程比在其他語言中要容易得多,仍然有一些概念需要掌握。要記住的一件重要的事情是 main() 函數也是一個線程,并可用來做有用的工作。程序員只有在需要多個線程時才需要創建新的線程。

    Thread 類
    Thread 類是一個具體的類,即不是抽象類,該類封裝了線程的行為。要創建一個線程,程序員必須創建一個從 Thread 類導出的新類。程序員必須覆蓋 Thread 的 run() 函數來完成有用的工作。用戶并不直接調用此函數;而是必須調用 Thread 的 start() 函數,該函數再調用 run()。下面的代碼說明了它的用法:

    創建兩個新線程

    import java.util.*;

    class TimePrinter extends Thread {
        int pauseTime;

        String name;

        public TimePrinter(int x, String n) {
            pauseTime = x;
            name = n;
        }

        public void run() {
            while (true) {
                try {
                    System.out.println(name + ":"
                            + new Date(System.currentTimeMillis()));
                    Thread.sleep(pauseTime);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }

        static public void main(String args[]) {
            TimePrinter tp1 = new TimePrinter(1000, "Fast Guy");
            tp1.start();
            TimePrinter tp2 = new TimePrinter(3000, "Slow Guy");
            tp2.start();

        }
    }

    在本例中,我們可以看到一個簡單的程序,它按兩個不同的時間間隔(1 秒和 3 秒)在屏幕上顯示當前時間。這是通過創建兩個新線程來完成的,包括 main() 共三個線程。但是,因為有時要作為線程運行的類可能已經是某個類層次的一部分,所以就不能再按這種機制創建線程。雖然在同一個類中可以實現任意數量的接口,但 Java 編程語言只允許一個類有一個父類。同時,某些程序員避免從 Thread 類導出,因為它強加了類層次。對于這種情況,就要 runnable 接口。

    Runnable 接口
    此接口只有一個函數,run(),此函數必須由實現了此接口的類實現。但是,就運行這個類而論,其語義與前一個示例稍有不同。我們可以用 runnable 接口改寫前一個示例。(不同的部分用黑體表示。)

    創建兩個新線程而不強加類層次

    import java.util.*;

    class TimePrinter implements Runnable {
        int pauseTime;

        String name;

        public TimePrinter(int x, String n) {
            pauseTime = x;
            name = n;
        }

        public void run() {
            while (true) {
                try {
                    System.out.println(name + ":"
                            + new Date(System.currentTimeMillis()));
                    Thread.sleep(pauseTime);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }

        static public void main(String args[]) {
            Thread t1 = new Thread(new TimePrinter(1000, "Fast Guy"));
            t1.start();
            Thread t2 = new Thread(new TimePrinter(3000, "Slow Guy"));
            t2.start();

        }
    }

    請注意,當使用 runnable 接口時,您不能直接創建所需類的對象并運行它;必須從 Thread 類的一個實例內部運行它。許多程序員更喜歡 runnable 接口,因為從 Thread 類繼承會強加類層次。

    synchronized 關鍵字
    到目前為止,我們看到的示例都只是以非常簡單的方式來利用線程。只有最小的數據流,而且不會出現兩個線程訪問同一個對象的情況。但是,在大多數有用的程序中,線程之間通常有信息流。試考慮一個金融應用程序,它有一個 Account 對象,如下例中所示:

    一個銀行中的多項活動

    public class Account {
        String holderName;

        float amount;

        public Account(String name, float amt) {
            holderName = name;
            amount = amt;
        }

        public void deposit(float amt) {
            amount += amt;
        }

        public void withdraw(float amt) {
            amount -= amt;
        }

        public float checkBalance() {
            return amount;
        }
    }

    在此代碼樣例中潛伏著一個錯誤。如果此類用于單線程應用程序,不會有任何問題。但是,在多線程應用程序的情況中,不同的線程就有可能同時訪問同一個 Account 對象,比如說一個聯合帳戶的所有者在不同的 ATM 上同時進行訪問。在這種情況下,存入和支出就可能以這樣的方式發生:一個事務被另一個事務覆蓋。這種情況將是災難性的。但是,Java 編程語言提供了一種簡單的機制來防止發生這種覆蓋。每個對象在運行時都有一個關聯的鎖。這個鎖可通過為方法添加關鍵字 synchronized 來獲得。這樣,修訂過的 Account 對象(如下所示)將不會遭受像數據損壞這樣的錯誤:

    對一個銀行中的多項活動進行同步處理

    public class Account {
        String holderName;

        float amount;

        public Account(String name, float amt) {
            holderName = name;
            amount = amt;
        }

        public synchronized void deposit(float amt) {
            amount += amt;
        }

        public synchronized void withdraw(float amt) {
            amount -= amt;
        }

        public float checkBalance() {
            return amount;
        }
    }

    deposit() 和 withdraw() 函數都需要這個鎖來進行操作,所以當一個函數運行時,另一個函數就被阻塞。請注意,checkBalance() 未作更改,它嚴格是一個讀函數。因為 checkBalance() 未作同步處理,所以任何其他方法都不會阻塞它,它也不會阻塞任何其他方法,不管那些方法是否進行了同步處理。

    Java 編程語言中的高級多線程支持

    線程組
    線程是被個別創建的,但可以將它們歸類到線程組中,以便于調試和監視。只能在創建線程的同時將它與一個線程組相關聯。在使用大量線程的程序中,使用線程組組織線程可能很有幫助。可以將它們看作是計算機上的目錄和文件結構。

    線程間發信
    當線程在繼續執行前需要等待一個條件時,僅有 synchronized 關鍵字是不夠的。雖然 synchronized 關鍵字阻止并發更新一個對象,但它沒有實現線程間發信。Object 類為此提供了三個函數:wait()、notify() 和 notifyAll()。以全球氣候預測程序為例。這些程序通過將地球分為許多單元,在每個循環中,每個單元的計算都是隔離進行的,直到這些值趨于穩定,然后相鄰單元之間就會交換一些數據。所以,從本質上講,在每個循環中各個線程都必須等待所有線程完成各自的任務以后才能進入下一個循環。這個模型稱為屏蔽同步,下例說明了這個模型:

    屏蔽同步

    public class BSync {
        int totalThreads;

        int currentThreads;

        public BSync(int x) {
            totalThreads = x;
            currentThreads = 0;
        }

        public synchronized void waitForAll() {
            currentThreads++;
            if (currentThreads < totalThreads) {
                try {
                    wait();
                } catch (Exception e) {
                }
            } else {
                currentThreads = 0;
                notifyAll();
            }
        }
    }

    當對一個線程調用 wait() 時,該線程就被有效阻塞,只到另一個線程對同一個對象調用 notify() 或 notifyAll() 為止。因此,在前一個示例中,不同的線程在完成它們的工作以后將調用 waitForAll() 函數,最后一個線程將觸發 notifyAll() 函數,該函數將釋放所有的線程。第三個函數 notify() 只通知一個正在等待的線程,當對每次只能由一個線程使用的資源進行訪問限制時,這個函數很有用。但是,不可能預知哪個線程會獲得這個通知,因為這取決于 Java 虛擬機 (JVM) 調度算法。

    將 CPU 讓給另一個線程
    當線程放棄某個稀有的資源(如數據庫連接或網絡端口)時,它可能調用 yield() 函數臨時降低自己的優先級,以便某個其他線程能夠運行。

    守護線程
    有兩類線程:用戶線程和守護線程。用戶線程是那些完成有用工作的線程。守護線程是那些僅提供輔助功能的線程。Thread 類提供了 setDaemon() 函數。Java 程序將運行到所有用戶線程終止,然后它將破壞所有的守護線程。在 Java 虛擬機 (JVM) 中,即使在 main 結束以后,如果另一個用戶線程仍在運行,則程序仍然可以繼續運行。

    避免不提倡使用的方法
    不提倡使用的方法是為支持向后兼容性而保留的那些方法,它們在以后的版本中可能出現,也可能不出現。Java 多線程支持在版本 1.1 和版本 1.2 中做了重大修訂,stop()、suspend() 和 resume() 函數已不提倡使用。這些函數在 JVM 中可能引入微妙的錯誤。雖然函數名可能聽起來很誘人,但請抵制誘惑不要使用它們。

    調試線程化的程序
    在線程化的程序中,可能發生的某些常見而討厭的情況是死鎖、活鎖、內存損壞和資源耗盡。

    死鎖
    死鎖可能是多線程程序最常見的問題。當一個線程需要一個資源而另一個線程持有該資源的鎖時,就會發生死鎖。這種情況通常很難檢測。但是,解決方案卻相當好:在所有的線程中按相同的次序獲取所有資源鎖。例如,如果有四個資源 —A、B、C 和 D — 并且一個線程可能要獲取四個資源中任何一個資源的鎖,則請確保在獲取對 B 的鎖之前首先獲取對 A 的鎖,依此類推。如果“線程 1”希望獲取對 B 和 C 的鎖,而“線程 2”獲取了 A、C 和 D 的鎖,則這一技術可能導致阻塞,但它永遠不會在這四個鎖上造成死鎖。

    活鎖
    當一個線程忙于接受新任務以致它永遠沒有機會完成任何任務時,就會發生活鎖。這個線程最終將超出緩沖區并導致程序崩潰。試想一個秘書需要錄入一封信,但她一直在忙于接電話,所以這封信永遠不會被錄入。

    內存損壞
    如果明智地使用 synchronized 關鍵字,則完全可以避免內存錯誤這種氣死人的問題。

    資源耗盡
    某些系統資源是有限的,如文件描述符。多線程程序可能耗盡資源,因為每個線程都可能希望有一個這樣的資源。如果線程數相當大,或者某個資源的侯選線程數遠遠超過了可用的資源數,則最好使用資源池。一個最好的示例是數據庫連接池。只要線程需要使用一個數據庫連接,它就從池中取出一個,使用以后再將它返回池中。資源池也稱為資源庫。

    調試大量的線程
    有時一個程序因為有大量的線程在運行而極難調試。在這種情況下,下面的這個類可能會派上用場:

    public class Probe extends Thread {
        public Probe() {
        }

        public void run() {

            while (true) {
                Thread[] x = new Thread[100];
                Thread.enumerate(x);

                for (int i = 0; i < 100; i++) {
                    Thread t = x[i];
                    if (t == null)
                        break;
                    else
                        System.out.println(t.getName() + "\t" + t.getPriority()
                                + "\t" + t.isAlive() + "\t" + t.isDaemon());
                }
            }
        }
    }

    限制線程優先級和調度
    Java 線程模型涉及可以動態更改的線程優先級。本質上,線程的優先級是從 1 到 10 之間的一個數字,數字越大表明任務越緊急。JVM 標準首先調用優先級較高的線程,然后才調用優先級較低的線程。但是,該標準對具有相同優先級的線程的處理是隨機的。如何處理這些線程取決于基層的操作系統策略。在某些情況下,優先級相同的線程分時運行;在另一些情況下,線程將一直運行到結束。請記住,Java 支持 10 個優先級,基層操作系統支持的優先級可能要少得多,這樣會造成一些混亂。因此,只能將優先級作為一種很粗略的工具使用。最后的控制可以通過明智地使用 yield() 函數來完成。通常情況下,請不要依靠線程優先級來控制線程的狀態。

    小結
    本文說明了在 Java 程序中如何使用線程。像是否應該使用線程這樣的更重要的問題在很大程序上取決于手頭的應用程序。決定是否在應用程序中使用多線程的一種方法是,估計可以并行運行的代碼量。并記住以下幾點:

    使用多線程不會增加 CPU 的能力。但是如果使用 JVM 的本地線程實現,則不同的線程可以在不同的處理器上同時運行(在多 CPU 的機器中),從而使多 CPU 機器得到充分利用。
    如果應用程序是計算密集型的,并受 CPU 功能的制約,則只有多 CPU 機器能夠從更多的線程中受益。
    當應用程序必須等待緩慢的資源(如網絡連接或數據庫連接)時,或者當應用程序是非交互式的時,多線程通常是有利的。
    基于 Internet 的軟件有必要是多線程的;否則,用戶將感覺應用程序反映遲鈍。例如,當開發要支持大量客戶機的服務器時,多線程可以使編程較為容易。在這種情況下,每個線程可以為不同的客戶或客戶組服務,從而縮短了響應時間。

    某些程序員可能在 C 和其他語言中使用過線程,在那些語言中對線程沒有語言支持。這些程序員可能通常都被搞得對線程失去了信心。

    posted @ 2007-07-30 09:36 比特鼠 閱讀(209) | 評論 (0)編輯 收藏

    眾所周知, Java在從XML文件中裝載內容到內存過程中,不論用何種方式,IO操作的開銷都無可避免。本文嘗試比較dom4j中的XPP3和SAX兩種方式裝載XML文件的性能,以便將IO操作的開銷降到最小!

    package gz.lwm;

    import java.io.File;
    import org.apache.log4j.Logger;
    import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XPP3Reader;

    public class TestDom4j {
     private static final Logger log = Logger.getLogger(TestDom4j.class);
     private static long bt; 
     
     public static void main(String[] args) {
      Document doc = DocumentHelper.createDocument();   
      //先運行getXmlSAX()
      bt = System.currentTimeMillis();
      String strXml = getXmlSAX("xml/test.xml");
      if(log.isDebugEnabled()){
       log.debug("\ngetXmlSAX() use time: " + (System.currentTimeMillis() - bt) + " millis\n");
      }

      //再運行getXmlXPP3()
      bt = System.currentTimeMillis();
      String s1 =getXmlXPP3("xml/test.xml");
      if(log.isDebugEnabled()){
       log.debug("\ngetXmlXPP3() use time: " + (System.currentTimeMillis() - bt) + " millis\n");
      }
      
      
     }
     
     public static String getXmlSAX(String xmlFile){
      String result = "";
      try {
       SAXReader reader = new SAXReader();
       Document document = reader.read(new File(xmlFile));
       result = document.asXML();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
     }
     
     public static String getXmlXPP3(String xmlFile){
      String result = "";
      try {
       XPP3Reader reader = new XPP3Reader();
       Document document = reader.read(new File(xmlFile));
       result = document.asXML();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return result;
     }


     
    }

    有沒有這一句"Document doc = DocumentHelper.createDocument()",對性能的影響很大,特別是對大xml文件(盡管并沒有使用doc)

    另外, getXmlXSAX()和getXmlXPP3()運行的先后次序對性能的影響也很大!

    測試:
        在我的機器上,對一個100k左右的XML文件進行多次測試后的均值結果為:

        getXmlXPP3() use time: 265 millis
        ...
        getXmlXSAX() use time: 359 millis
        ...

    結論:
        通過比較,在讀取XML文件上,XPP3略為優于SAX!


    注意:

    要運行例子,classpath需包含:
    dom4j-1.6.1.jar
    jaxen-1.1-beta-10.jar
    log4j-1.2.9.jar
    pull-parser-2.1.10.jar
    xpp3-1.1.4c.jar


    參考:
    dom4j :  http://www.dom4j.org/
    XPP   :  http://www.extreme.indiana.edu/xgws/xsoap/xpp/

    posted @ 2007-05-19 00:39 比特鼠 閱讀(2509) | 評論 (0)編輯 收藏

       Namespace namespace ...

       //第一種方法
       Document doc = DocumentHelper.createDocument();
       Element root = doc.addElement("Root", namespace.getURI());
       Element eResultMessage = root.addElement("ResultMessage");

       結果為:
       <Root xmlns="http://aaaaaa"><ResultMessage>...</ResultMessage></Root>



       //第二種方法
       Document doc = DocumentHelper.createDocument();
       Element root = doc.addElement(("Root");
       root.add(namespace);
       Element eResultMessage = root.addElement("ResultMessage");
       
       結果為:
       <Root xmlns="
    http://aaaaaa"><ResultMessage xmlns="">...</ResultMessage></Root>

    posted @ 2007-05-17 21:08 比特鼠 閱讀(2659) | 評論 (0)編輯 收藏

    僅列出標題
    共6頁: 上一頁 1 2 3 4 5 6 下一頁 
    主站蜘蛛池模板: 日日夜夜精品免费视频| 99爱视频99爱在线观看免费| 女人被免费视频网站| 亚洲av永久综合在线观看尤物| 少妇无码一区二区三区免费| 久久精品国产亚洲av高清漫画 | 亚洲日韩AV无码一区二区三区人| 亚洲免费网站观看视频| 国产成+人+综合+亚洲专| 成年女人喷潮毛片免费播放| 337p日本欧洲亚洲大胆人人| 国产精品二区三区免费播放心 | 国产亚洲sss在线播放| 最近中文字幕无吗免费高清| 亚洲综合偷自成人网第页色| 毛片基地免费视频a| 亚洲aⅴ无码专区在线观看| 亚洲综合色成在线播放| 中文字幕免费在线看线人动作大片| 亚洲色婷婷六月亚洲婷婷6月| 久久国产精品一区免费下载| 亚洲自偷自拍另类图片二区| 青娱乐免费在线视频| 最新亚洲人成无码网站| 亚洲无人区一区二区三区| 久久99精品免费视频| 国产成人亚洲合集青青草原精品| 成年人在线免费观看| 一级毛片免费在线| 亚洲欧洲第一a在线观看| 女人毛片a级大学毛片免费| 男人和女人高潮免费网站| 亚洲国产另类久久久精品黑人| 91精品国产免费久久国语蜜臀| 亚洲精华国产精华精华液| 亚洲色欲一区二区三区在线观看| 97久久免费视频| 午夜免费国产体验区免费的| 亚洲系列国产精品制服丝袜第 | 亚洲色成人WWW永久网站| 青青青免费国产在线视频小草|