微科社区,轻松开发从此开始! 请登陆 免费注册

微科社区

当前位置:首页 > Java平台 > J2SE >

用java多线程统计超大数据文件(1TB以上)中出现次

时间:2014-04-15 11:13  浏览:努力统计中...
各位亲,现在有一个需求是: 如何在一台多核服务器上快速的统计一个超大的数据文件(1TB以上)中出现次数最多的人名。文件内容格式如下: 张三 李四 王五 赵六 ........... 要求用
各位亲,现在有一个需求是:
如何在一台多核服务器上快速的统计一个超大的数据文件(1TB以上)中出现次数最多的人名。文件内容格式如下:
张三
李四
王五
赵六
...........

要求用java多线程实现。
ps:之前用hashcode取模的方式实现了,但是效果不是太理想,想换成多线程处理,求高人指点。


我的思路:
用hash(var)%1024分成1024个桶,然后分桶来统计各桶内次数最多的人名,最后找到所有人名中出现最多的。

时间开销:O(n)

不知道LZ说的效果不太理想是指哪方面不理想?

嗯,你说的这种方式我已经实现了的,跟你说的思路是一样的。现在就想换成多线程的方式实现,不知道有没有这方面比较好的解决方案,多线程应该处理起来(效率)效果应该是最优的。

线程池就是在 1楼基础上,分配开来。

我觉得你这个业务场景用多线程没什么太多帮助,按照我的思路,就是把文件扫两遍,不会有很多时间阻塞在IO上,所以多线程没什么作用

如果你想提升效率,可以考虑用分布式计算,单机的话,单线程扫文件应该用不了多久的

多线程实现是不是有些困难呢,求高人现身。

CountWordsThread.java

public class CountWordsThread implements Runnable{
private FileChannel fileChannel = null;
private FileLock lock = null;
private MappedByteBuffer mbBuf = null;
private Map<String, Integer> hashMap = null;

public CountWordsThread(File file, long start, long end) {
try {
// 得到当前文件的通道
fileChannel = new RandomAccessFile(file, "rw").getChannel();
// 锁定当前文件的部分
lock = fileChannel.lock(start, end, false);
// 对当前文件片段建立内存映射,如果文件过大需要切割成多个片段
mbBuf = fileChannel.map(FileChannel.MapMode.READ_ONLY, start, end);
// 创建HashMap实例存放处理结果
hashMap = new HashMap<String,Integer>();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String str = Charset.forName("UTF-8").decode(mbBuf).toString();
StringTokenizer token = new StringTokenizer(str);
String word = null;
while(token.hasMoreTokens()) {
// 将处理结果放到一个HashMap中
word = token.nextToken().toString().trim();
if(null != hashMap.get(word)) {
hashMap.put(word, hashMap.get(word) + 1);
} else {
hashMap.put(word, 1);
}
}
try {
// 释放文件锁
lock.release();
// 关闭文件通道
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}

//获取当前线程的执行结果
public Map<String, Integer> getResultMap() {
return hashMap;
}
}

DealFileText.java

public class DealFileText {

// 要处理的文件
private File file = null;

// 线程数数组
private CountWordsThread[] threads = null;

private List<Thread> listThread = null;

public DealFileText(File file){
this.file = file;
}

public DealFileText(File file , int threadNum){
this.file = file;
this.threads = new CountWordsThread[threadNum];
}

public void dealFile(){
final CountWordsThread thread1 = new CountWordsThread(file, 0, file.length()/2);
final CountWordsThread thread2 = new CountWordsThread(file, file.length()/2, file.length());
final Thread t1 = new Thread(thread1);
final Thread t2 = new Thread(thread2);
// 开启两个线程分别处理文件的不同片段
t1.start();
t2.start();
Thread mainThread = new Thread() {
public void run() {
while(true) {
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线------