java 文件多线程并行读取

1.针对大文件的读写的情景的缺点:

1.考虑到大文件的文件size过大导致读取速度慢,并且大文件读取进来后数据太多导致处理需要花费更多时间,并且IO过程中,CPU处于空闲,很大的浪费了CPU的性能。

2. IO需要将文件从磁盘通过DMA拷贝到内核缓冲区,然后从内核缓冲区拷贝到用户缓冲期,如果文件过大,那么这个拷贝也花时间

2.利用多线程和map内存映射加速读取

1.使用map避免文件从内核缓冲期复制到用户缓冲期。

2.加上多线程并行对一个文件进行IO和数据处理。

3. 考虑到通用性,线程之间进行同步需要避免读取重复的数据,因此使用一个volatile变量记录当前读取的index下标,然后每个线程读取数据使用cas更新下标。

java代码如下:

package List;

import javafx.concurrent.Worker;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Description: 实现多线程对同一个文件的并行读写
 *
 *
 * @author Mayber
 * @date Created on 2022/4/10
 */
public class ParalFile {

    

    public AtomicInteger index = new AtomicInteger(0);
    public long size;

    public int buffer_size;

    RandomAccessFile orign_raf;
    RandomAccessFile target_raf;
    FileChannel orignFileChannel;
    FileChannel targetFileChannel;

    public ParalFile(File orign,int buffer_size) throws FileNotFoundException {
        RandomAccessFile orign_raf = new RandomAccessFile(orign,"rw");
        // RandomAccessFile target_raf = new RandomAccessFile(target,"rw");
        this.orignFileChannel = orign_raf.getChannel();
        this.targetFileChannel = target_raf.getChannel();
        this.buffer_size = buffer_size;
        this.size = orign.length();
        System.out.println("构造完毕");
    }


    class ReadTask implements Runnable{
        @Override
        public void run() {
            // 这个任务中需要使用cas获取到当前的 index,并且读取index+buffer值,然后将index改为
            int cur_index;
            System.out.println("执行");
            while((cur_index = index.get())<size){

                int target_index = (cur_index+buffer_size)>size? (int)size :cur_index+buffer_size;


                if(index.compareAndSet(cur_index,target_index+1)){
                    //如果cas 成功就进行读写操作
                 
                    System.out.println(Thread.currentThread().getName()+"读取了cur_index"+cur_index+"到"+target_index+"的缓冲数据");
                    byte[] content = readFile(cur_index,target_index);

                    // 读取到了内容可以在下面进行一些别的处理操作

                }
            }

        }

        public byte[] readFile(int orign_index,int target_index){

            // 读取文件,使用一个map内存映射进行读取,可以加速读取吧
            MappedByteBuffer map;
            byte[] byteArr = new byte[target_index-orign_index];
            try {
                map = orignFileChannel.map(FileChannel.MapMode.READ_ONLY,orign_index,target_index-orign_index);

                map.get(byteArr,0,target_index-orign_index);
            } catch (Exception e) {
                System.out.println("读取"+orign_index+"到"+target_index+"失败");
                e.printStackTrace();
            }
            return byteArr;


        }


    }

    class WriteTask implements Runnable{

        @Override
        public void run() {

            byte[] a = new byte[1024];
            int cur_index;
            System.out.println("执行");
            while((cur_index = index.get())<size){

                int target_index = (cur_index+buffer_size)>size? (int)size :cur_index+buffer_size;


                if(index.compareAndSet(cur_index,target_index+1)){
                    //如果cas 成功就进行读写操作
                    //成功
                    System.out.println(Thread.currentThread().getName()+"写了cur_index"+cur_index+"到"+target_index+"的缓冲数据");
                    writeFile(cur_index,target_index,a);

                    // 读取

                }
            }
        }

        public void writeFile(int orign_index,int target_index,byte[] content){
            //然后进行写
            // 读取文件,使用一个map内存映射进行读取,可以加速读取吧
            MappedByteBuffer map;
            byte[] byteArr = new byte[target_index-orign_index];
            try {
                map = targetFileChannel.map(FileChannel.MapMode.READ_ONLY,orign_index,target_index-orign_index);

                map.position();
                map.put(content);
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }

    public static void main(String[] args) throws FileNotFoundException {

        File orign = new File("D:\\work_space\\project\\leetcode\\src\\test.txt");
        ParalFile pf = new ParalFile(orign,30);
        ThreadPoolExecutor poll = new ThreadPoolExecutor(4,5,1, TimeUnit.HOURS,new LinkedBlockingDeque<>(10) );

        for(int i=0;i<5;i++){
            poll.execute(pf.new ReadTask());
        }



    }




}


3. 大文件性能测试

补档,等

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值