皮杜妮

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            887 Posts :: 3 Stories :: 7 Comments :: 0 Trackbacks
          電商系統需要記錄用戶行為,需要一個高并發高速寫入文件,考慮利用緩存和noi機制寫入數據,具體邏輯是2塊緩存區,一塊寫數據,一塊寫文件,交替進行,并且利用noi機制一次寫入數據。

          測試結果: 1億條數據用時93秒,生產58個100m文件。每一條953納秒。

          package io.netty.example.http.snoop;

          import java.io.FileOutputStream;
          import java.io.RandomAccessFile;
          import java.nio.ByteBuffer;
          import java.nio.CharBuffer;
          import java.nio.MappedByteBuffer;
          import java.nio.channels.FileChannel;
          import java.nio.charset.Charset;
          import java.nio.charset.CharsetDecoder;
          import java.nio.charset.CharsetEncoder;
          import java.text.ParseException;
          import java.text.SimpleDateFormat;
          import java.util.Date;

          public class WriterFile {


                  // 指定大小為 1024 的緩沖區
                  public static ByteBuffer bytebufferone = ByteBuffer.allocate(102400000);
                  public static ByteBuffer bytebuffertwo = ByteBuffer.allocate(102400000);
                  public static boolean checkbuffer =true;
                  
                  public static void main(String[] args) {
                       long start = System.nanoTime();  
                        
                          
                      for(int i=0;i<100000000;i++){
                          
                          if(checkbuffer)
                              processone("123abc"+i+"\r\n");
                          else
                              prcesstwo("123abc"+i+"\r\n");    
                      }
                      long end = System.nanoTime();  
                      System.out.println((end - start)+"耗時");  
                  }
                  /**
                   * bytebuffertwo寫日志
                   */
                  public static void prcesstwo(String log)
                  {
                      //寫bytebuff
                       boolean onecheck=checkposition(log,bytebuffertwo);
                      if(onecheck)
                          writerbuffer(log,bytebuffertwo);
                      //寫文件
                      else{
                          checkbuffer=true;
                          writerbuffer(log,bytebufferone);
                          writerfile(bytebuffertwo);
                      }
                  }
                  
                  /**
                   * bytebufferone寫日志
                   * @param log
                   */
                  public static  void  processone(String log)
                  {
                          //寫bytebuff
                           boolean onecheck=checkposition(log,bytebufferone);
                          if(onecheck){
                              
                              writerbuffer(log,bytebufferone);
                          }
                          //寫文件
                          else{
                              checkbuffer=false;
                              writerbuffer(log,bytebuffertwo);
                              writerfile(bytebufferone);
                          }
                      }
                  
                  /**
                   * 判斷緩存是否可以寫下日志
                   * @param log
                   * @return
                   */
                  public static  boolean checkposition(String log,ByteBuffer bytebuffer)
                  {

                      if(2*log.getBytes().length>bytebuffer.limit()-bytebuffer.position())
                      {
                          return false;
                      }
                      else
                      {
                          return true;
                      }
                  }
                  /**
                   * 寫日志到緩存,并且返回緩存指針位置
                   * @param log
                   * @return
                   */
                  public static   int  writerbuffer(String log,ByteBuffer bytebuffer )
                  {
                      for (int i = 0; i < log.length(); i++) {
                          bytebuffer.putChar(log.charAt(i));
                      }
                      return bytebuffer.position();
                  }
                  /**
                   * 寫文件
                   * @param filename
                   */
                  public static  void  writerfile(ByteBuffer bytebuffer)
                  {
                      try{
                          FileOutputStream fos = new FileOutputStream(Datefile());
                          FileChannel fc = fos.getChannel();
                          bytebuffer.flip();
                          fc.write(bytebufferone);
                          fc.close();
                          fos.close();
                          bytebuffer.clear();
                      }
                      catch(Exception ex)
                      {
                          ex.printStackTrace();
                      }
                  }
                  /**
                   * 文件名按日期生產
                   * @param str
                   * @return
                   */
                  public static String Datefile() {
                         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
                         String str = format.format(new Date());
                         return "d:/test/"+str+".txt";
                  }
          }


          附帶一個普通的nio讀寫
                  public static  void test()
                  {
                      try{
                      FileOutputStream fos = new FileOutputStream("d:/nio.txt");
                      // 得到文件通道
                      FileChannel fc = fos.getChannel();
                      // 指定大小為 1024 的緩沖區
                      ByteBuffer bf = ByteBuffer.allocate(1024);
                      // 要寫入文件的字符串
                      String greeting = "Hello111";
                      // 把以上字符串逐字放入緩沖區
                      for (int i = 0; i < greeting.length(); i++) {
                          bf.putChar(greeting.charAt(i));
                      }
                      // 記得執行這個方法,使得 position=0, limit=30, 才能寫入正確的數據
                      // 否則 position 為 30, limit 為 1024,將會把 30 之后的全部空數據(0) 填到文件中
                      
                      System.out.println(greeting.getBytes().length);
                      System.out.println(bf.position());
                      System.out.println(bf.limit());
                      
                      bf.flip();
                      // 緩沖區數據寫入到文件中,會把緩沖區中從 position 到 limit 之間的數據寫入文件
                      fc.write(bf);
                      fc.close(); // 關閉文件通道
                      fos.close(); // 關閉文件輸出流
                      }catch(Exception e){
                       e.printStackTrace();
                      
                      }
                  }
          posted on 2013-11-23 11:16 豬眼睛 閱讀(132) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 抚州市| 桦甸市| 文昌市| 灵山县| 柞水县| 信丰县| 沐川县| 东莞市| 武川县| 吉安市| 东兴市| 措美县| 开封市| 宜君县| 太原市| 即墨市| 丹江口市| 绥德县| 桓仁| 错那县| 鹿邑县| 涡阳县| 冀州市| 孙吴县| 平陆县| 海盐县| 勃利县| 卓尼县| 思南县| 虞城县| 调兵山市| 探索| 黔江区| 成安县| 武隆县| 屏东市| 蓬溪县| 台中县| 昌图县| 泉州市| 双流县|