go语言多线程读取文件 go 多线程模型( 二 )


为了充分利用多线程读取 , 就需要把文件划分成多个区域,供每个线程读取 。那么就需要有一个算法来计算出每个线程读取的开始位置和结束位置 。那么首先根据配置的线程数和文件的总长度计,算出每个线程平均分配的读取长度 。
但是有一点 , 由于文件是纯文本文件,必须按行来处理 , 如果分割点在某一行中间 , 那么这一行数据就会被分成两部分,分别由两个线程同时处理,这种情况是不能出现的 。所以各个区域的结束点上的字符必须是换行符 。第一个区域的开始位置是0,结束位置首先设为(文件长度/线程数),如果结束点位置不是换行符 , 就只能加1,直到是换行符位置 。
如果多线程操作,那么需要保证多个线程操作同一个对象,此外请保证先有线程放进内容 , 其他线程才能拿出数据 。
如何用多线程读取大文件并且做数据处理,100先说几个要点:
a、文件在操作系统级,有描述符标记,关联到打开的文件表项,文件表项纪录了一个很重要的信息,当前文件的指针;
b、cpu要干的工作比读文件快不,读一次文件的速度要慢于cpu处理一次的速度,没必要多多线程,多线程提升不了多少性能,还增加编程的难度,单线程处理即可 。
c、待处理文件,必须知道一定的边界值,如分页边界或单条纪录边界 。
有了上面的前提,每个线程维护单独的缓冲区,缓存区大小就是c点提到的边界纪录大小 。线程启动 , 把缓冲区读满,处理数据 。此处有个要点,必须做文件锁,把要读的边界锁住 。否则读出来的数据会产生混乱 。(如果强行打开多个不同的文件不划算,内存占用可能会过多) 。产生混乱的原因简单 , 读文件实际上是进行系统调用,系统调用有自己的缓冲区 , 这缓冲区未必跟你设置的缓冲区一样大 。多次读多次移动指针,不加文件锁处理的数据必定会乱 。
文件锁两种方式加锁,对整个文件加锁,对字节区间加锁 。都不是什么难事 。
实现方式1:对整个文件加锁,因为我们要保证的是读到的数据别混乱 。
实现方式2:如果内存足够大,维护n个独立的文件描述符,这些文件描述符必须有独立的文件指针,操作系统上有对应实现 。每个线程操作未读纪录,这么做还需要维护共享的已读纪录指针 。防止重复处理 。这么做处理完成如果需要按顺序合并文件是难点 。处理过的数据有新的纪录边界 。要视实际情况而定能不能这么做 。写程序要优先保证的是正确性,之后才是提升效率 。
我说的理论 , 依据是操作系统提供的api处理 。别的语言要依赖操作系统运行 。原理差不多,目标语言有没有操作系统提供的api强悍 。依据使用的目标语言而定 。绝大多数能叫编程语言的语言都会提供操作系统api对应的方法 。(脚本语言例外,如shell , perl,javascript,vbscript,就可能没这么强的控制能力 。),java,objective-c,swift,php,python一般是不会有问题的 。
能否多线程同时读取多个文件?参考如下go语言多线程读取文件:
【go语言多线程读取文件 go 多线程模型】using System.threading;
Metux m=new Metux();
//假设你的操作XML文件的方法为UpdateXml
void UpdataXml()
{
m.WaitOne(); //当一个线程正在使用该方法的时候go语言多线程读取文件,锁定该方法,使其go语言多线程读取文件他线程处于等待状态
//...对XML的操作
m.ReleaseMetux(); //使用完了 , 释放锁,让其go语言多线程读取文件他线程继续使用

推荐阅读