如何用多线程读取大文件并且做数据处理,100分急等解答!

ooooeee 2007-12-09 10:46:10
小弟刚学java,,但对java的多线程以及其他一些东西不太熟悉,尤其是1.5之后似乎原来的并发机制已被更优的方法代替了,更让人不知用什么才好。现在正在做一个实习项目,要求如下:
1,有10个文本文件,每个220M左右,每个文件记录大约2千万条,每条记录格式相同,包括每条记录的原始时间戳,但每条记录中也有些是无用的信息,处理时去掉。
2,要产生用户指定的记录条数,并对其做相应的处理(细节略)
3,将产生的记录放入一个队列中,生产者在队列满时阻塞,消费者在队列空时等待

我的问题是:
1,想用多线程来提高处理的效率,想请问大家的是,有没有办法用多个线程读取一个文件的内容来提高速度,比如线程1读取文件的第一行,线程2同时读取第二行。。。如果这点做不到,那是不是应该把读文件和处理记录放在不同的线程中来提高效率?但是处理记录的方法必须依赖于读到的每一行的内容,如何在不同的线程中实现呢?
2,老师的要求是用一个指定大小的队列来存放这些记录,并根据每条记录的原始时间戳来生成新的时间戳(只是为了保持原有的先后顺序),然后将它们按时间戳排序,等待用户来拿,而用户取得的记录将根据记录的时间戳来决定何时发送给其他人(这点不用我实现)。我本来想用PriorityQueue来实现,但是如果有多个线程在进行生产和获取记录,那么根本保证不了用户拿到所有的记录时是按时间戳排序的,更别说根据时间顺序发送出去了。。。老师说可以让用户自己实现一个sortedSet进行排序,那如果这家伙要生成2亿条记录,估计他得准备个2G内存来存储并排序这些数据了。。。有什么办法可以减少内存开销又获得比较好的性能呢?
3,上面那个queue的问题,好像不但解决不了时间戳的先后顺序,而且多线程在这个queue上根本没用武之地吧?只能一头进一头出,如果空了或者满了,再多的线程都得等着,加上同步的开销,好像还不如单线程来的快。我是否应该改用其他数据结构比如list什么的 加上多线程?
4,最头痛的一点,这个程序到时要部署到多个网络节点上去的,但是老师又说,原始数据太庞大,不想就这样放到每个节点上去。。。那如果不放上去怎么读取到足够的数据呢??用数据库会不会节省些空间开销?或者需要搞分布式?

花了好多时间了,多线程的东西还是一知半解,写程序写到郁闷死,最后发现照我现在的写法多线程还不如单线程快。。。更要命的是结构上还有很多东西没定下来,根本没法往下写了,各位大侠救救我吧!
...全文
1761 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
wocsok 2009-10-01
  • 打赏
  • 举报
回复
你的问题存在 异步中的同步 你可以参考下 事件驱动模型 写成事件监听器 来实现这些并发问题的处理机制
ooooeee 2007-12-15
  • 打赏
  • 举报
回复
再请教一个问题,如果用一个线程读映射到内存中的文件,这个线程将读到的每行内容分别放入N个buffer里,然后另外开辟N个线程,每个线程分别从不同的一个buffer里获得内容进行处理,并放入最终的queue中,这样速度能提高些吗?但是这样好像同步有些困难,我写的程序,虽然该生成的sub都生成了,但是有些处理线程会因为buffer空了一直wait,因为到最后别的线程都结束了,没人notify它了。。。是否需要个别的对象来进行同步??多线程实在太郁闷了。。
ooooeee 2007-12-14
  • 打赏
  • 举报
回复
谢谢bao110908大侠一直不厌其烦的回帖,关于时间戳的问题是这样的:
1,原始数据格式如下:
142 broadway.vera.org 2006-04-08 08:39:30

2,这里的时间是未处理前的时间戳,但是老师要求的是在用这些数据生成subscription的时候,客户可以指定所要生成sub的条数和时间间隔。比如说客户指定生成1000条sub,他们的时间跨度是10分钟,而程序从原始文件读到的记录可能时间跨度是1个月,那我就需要在保持原始记录的时间先后顺序的同时做相应的时间间隔压缩,把跨度一个月的记录的时间戳压缩到10分钟内,然后在queue中根据时间戳的先后顺序进行排序,这样用户在提取sub的时候,可以根据sub的时间戳决定何时发布这些sub,比如提取到的第一个sub的时间戳是0,那么就立即发布,第二个时间戳是3000,那么就3秒后发布,反正就是保证在10分钟内把这些sub发布出去就对了

是否将原始数据放到数据库比较好点?老师说如果我要用数据库,那就用轻量级的容易打成jar包和程序一起发布的,比如tinySQL之类的,不知道有没有人用这个小玩意儿?
  • 打赏
  • 举报
回复
不好意思,昨天没看到 :)

1,最后按照DATE的先后顺序生成相应的timestamp
不明白,DATE和Timestamp有些什么区别?两个都是时间戳之间的东西,能否举个例子?

2,并在queue中按timestamp进行排序
不明白,为什么要在Queue中排序呢?

3,可能我比较笨不能完全了解老外的想法,我还是没有看懂具体要做些什么,感觉越看越糊涂了……

如果不进行数据的转换,采用占用容量更小的数据类型来存储的话,采用集合类,
这个任务近乎是不可能完成的(限于内存)。

如果有必要把数据导入到数据库中好像更为合适一些。
ooooeee 2007-12-12
  • 打赏
  • 举报
回复
不好意思,我以为那些没太大关系呢。。。具体是这样的,老师要求做一个pub/sub系统的测试用API,以一个网站发布的搜索数据做源数据,根据指定参数(具体的有具体的query条数,或不同的user的个数,或者提交过M到N条query的user所提交的所有query条数)生成subscription,然后由pub/sub系统发布出去。源数据格式如下:
UID QUERYCONTENT DATE
源数据以UID排序,但是老师要求最后按照DATE的先后顺序生成相应的timestamp,并在queue中按timestamp进行排序,然后由client提取queue中的subscription,按timestamp规定的时间间隔发布。。。

不知道这样描述是否清楚。。。原描述是英文的,大概就这意思了。。
  • 打赏
  • 举报
回复
[size=30px]to: ooooeee[/size]

还有,bao110908朋友,请问你是C爱好者吗?看到你都用printf做输出嘛:D
_____________________________________________________________

嘿嘿,我不是C语言的爱好者,对C语言只知皮毛,之所以用printf,主要是格式
化输出更为方便的啦~~

3600多万条,就算一个文件也有36万条,近160多M,全部塞进Map中根本就是不
可能的!就算塞进去内存得开得很大。

你可能还没有完全理解我的意思,像上次那个2G文件的那个,人家一上来就把格
式、需求都说得很清楚。像你的这个,我到现在为止都不知道你的文件格式是什
么?具体要做些什么?(细节竟然略掉了)
像这种大文件,只能根据格式、需求
来找出算法的。

真的很抱歉,根本不能帮你想到什么实质性的办法!
z31404 2007-12-11
  • 打赏
  • 举报
回复
学习
ooooeee 2007-12-11
  • 打赏
  • 举报
回复
关于堆内存占用的问题,如果不用内置的集合类,那应该用什么呢?我这里不是要比较各行的内容,而是要确实的获得每行的内容并进行处理,转成int或其他类型行不通的吧?还有,如果map到内存去读,速度是快了,但是获得每行的内容变得更困难了,好像会得不偿失啊。。
ooooeee 2007-12-11
  • 打赏
  • 举报
回复
还有,bao110908朋友,请问你是C爱好者吗?看到你都用printf做输出嘛:D
xiyuan1999 2007-12-11
  • 打赏
  • 举报
回复
使用缓存 给缓冲区 不要都放在内存里面
ooooeee 2007-12-11
  • 打赏
  • 举报
回复
bao110908朋友,你的代码我正在研究学习中,因为是初学所以看的可能慢点,不过在此先向你以及楼上各位热心的朋友表示感谢。
因为时差关系,还有些问题等上课回来再请教你。。
PS:对nio的内存映射的使用还是不太明白,是不是如果只将文件的一部分映射到内存,比如映射到64M大小的buffer,下次我还想接着上次的地方继续读文件,那就必须在文件当前位置重新开个通道?
  • 打赏
  • 举报
回复
IO通道只有一个,采用多线程也是没有用的,而且很有可能出现错误。
  • 打赏
  • 举报
回复
楼主,不好意思,我不知道你看到了我在8楼给你的回复了吗?

曾经在CSDN回复过一个关于两个2G文件比较不同的问题,貌似与你的问题有异曲同工之处,你可以去参考一下:

http://topic.csdn.net/u/20071119/23/8af044b3-8c28-4db0-8303-4a8679f2356d.html

PS:我回复的代码在41~43楼。
ooooeee 2007-12-11
  • 打赏
  • 举报
回复
请问楼上什么地方不清楚呢?我现在最大的问题就是如何有效的处理大文件。
好像可以用nio进行文件映射,但一次映射整个160M的文件会不会大了点?但如果只映射部分文件,比如mappedbytebuffer大小设16M,因为我处理的时候需要按行来读记录,按换行符读缓存的话,肯定每次会有些剩下的,到时是不是还得把channel的position移回到上一行的结尾,保证能读取完整的一行,然后继续映射啊??
notruiyi 2007-12-11
  • 打赏
  • 举报
回复
问题一次说明白点.反正是看不懂,把所有情况都说清楚
ooooeee 2007-12-11
  • 打赏
  • 举报
回复
另外,我看到有个nio的例子,里面有指定MappedByteBuffer时如下语句:
static int length = 0x8FFFFFF; // 128 Mb
8FFFFFF怎么会是128Mb呢?就算从0算起,length也应该是7FFFFFF吧?
timbear 2007-12-11
  • 打赏
  • 举报
回复
学习中~
bukebuhao 2007-12-11
  • 打赏
  • 举报
回复
study
ooooeee 2007-12-10
  • 打赏
  • 举报
回复
那请问怎么用nio呢?看到都是一堆channel。。。实在不懂啊,是map到内存吗?我这个文件是应该是适合按行读取的,好像没找到nio里哪个可以readLine的类啊。。。
  • 打赏
  • 举报
回复
在32位结构下,JVM能使用的内存最大不可能超过2G,实际上使用java命令的-Xmx参数可以给到最大的也只有1G多一些。

要提高效率和降低内存占用,首先需要舍弃使用Java中的集合类来存储数据。
加载更多回复(10)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧