皮杜妮

  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 猪眼睛 阅读(113) 评论(0)  编辑  收藏 所属分类: Java