多线程计算TOP-K的问题与单线程计算结果不一致,求问题原因

闭门车 2016-09-01 01:37:11
先上单线程的代码,如下:

public class TopK {
static Map map=new HashMap(30000);
static int k=10;
/**
* @Title: main
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param args 设定文件
* @return void 返回类型
* @throws
*/
public static void main(String[] args) {
long begin=System.currentTimeMillis();
String encoding="UTF-8";
String filePath="E:\\nohup.out";
File file=new File(filePath);
InputStreamReader read;
try {
read = new InputStreamReader(new FileInputStream(file),encoding);
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while((lineTxt = bufferedReader.readLine()) != null){
String[] w= lineTxt.split(" ");
for(String s:w){
if(map.containsKey(s)){
if(!s.startsWith(" ")){
int tmp=(int)map.get(s);
map.put(s, tmp+1);
}
}else{
map.put(s, 1);
}

}
}
read.close();
int[] top= new int[k];
String[] topKey= new String[k];
System.out.println(map.size());
for (Object e : map.keySet()) {
int tmp=(int)map.get(e.toString());
sort(top,topKey,e.toString(),tmp);
}
for(String s:topKey){
System.out.println(s);
}
for(int s:top){
System.out.println(s);
}
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}//考虑到编码格式
catch (IOException e) {
e.printStackTrace();
}
long end=System.currentTimeMillis();
System.out.println(end-begin);
}
/**
*
* @Title: sort 排序,将出现频率最高的前移
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param top
* @param @param topKey
* @param @param key
* @param @param tmp 设定文件
* @return void 返回类型
* @throws
*/
public static void sort(int[] top,String[] topKey,String key,int tmp){
int i=9;
while(i>=0&&tmp>=top[i]){
i--;
}
if(i<9){
top[i+1]=tmp;
topKey[i+1]=key;
}
}
}

然后是多线程的:

public class TopK implements Runnable {
static Map map = new ConcurrentHashMap(30000);
static BlockingQueue<String> datas = new LinkedBlockingQueue<String>(
10000000);
static int k = 10;
Lock lock = new ReentrantLock();
private long begin = System.currentTimeMillis();
private int state = 1;

/**
* @Title: main
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param args 设定文件
* @return void 返回类型
* @throws
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final long begin = System.currentTimeMillis();
new Thread(new TopK()).run();

}

public static void sort(int[] top, String[] topKey, String key, int tmp) {
int i = 9;
while (i >= 0 && tmp >= top[i]) {
i--;
}
if (i < 9) {
top[i + 1] = tmp;
topKey[i + 1] = key;
}
}

@Override
public void run() {

new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
long begin = System.currentTimeMillis();
String encoding = "UTF-8";
String filePath = "E:\\nohup.out";
File file = new File(filePath);
// Map map1=new HashMap(30000);
// map1.put("1", 2);
InputStreamReader read;
try {
read = new InputStreamReader(new FileInputStream(file),
encoding);
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while ((lineTxt = bufferedReader.readLine()) != null) {
datas.add(bufferedReader.readLine());

// System.out.println(lineTxt);
}
read.close();
System.out.println("end read");
System.out.println(System.currentTimeMillis() - begin);
state = 2;
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}// 考虑到编码格式
catch (IOException e) {
e.printStackTrace();
}
}

}, "read file").start();
/**
* 读取并处理字符串到map中
*
* @author Administrator
*
*/
class Executestring implements Runnable {
// Lock lock= new ReentrantLock();
@Override
public void run() {
while (true) {
if (datas.isEmpty()) {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (!datas.isEmpty()) {
try {
String str = datas.take();
String[] strs = str.split(" ");
for (String s : strs) {
if (map.containsKey(s)) {
if (!s.startsWith(" ")) {
try {
lock.lock();
int tmp = (int) map.get(s);
map.put(s, tmp + 1);
} finally {
lock.unlock();
}
}
} else {
map.put(s, 1);
}

}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
System.out.println("end map put");
System.out.println(System.currentTimeMillis() - begin);
if (state == 2) {
break;
}
}
}

}
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
pool.execute(new Executestring());
}
pool.shutdown();
try {
boolean loop = true;
do { // 等待所有任务完成
loop = !pool.awaitTermination(100, TimeUnit.SECONDS); // 阻塞,直到线程池里所有任务结束
new Thread(new Runnable() {

@Override
public void run() {
System.out.println("begin sort");
// TODO Auto-generated method stub
int[] top = new int[k];
String[] topKey = new String[k];
System.out.println(map.size());
for (Object e : map.keySet()) {
int tmp = (int) map.get(e.toString());
sort(top, topKey, e.toString(), tmp);
}
for (String s : topKey) {
System.out.println(s);
}
for (int s : top) {
System.out.println(s);
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
System.out.println("this is end result");
}
}, "sort thead").start();
} while (loop);

} catch (InterruptedException e) {
e.printStackTrace();
}

}
}

执行出来的结果 单线程统计出来的次数远大于多线程的这种,为什么呢?哪段代码有问题?
用的nohup.out大概400M吧。
...全文
445 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
skgary 2016-09-02
  • 打赏
  • 举报
回复
请先按以下的思路定位一下问题: 1. 确认到底 哪个数值是正确的,单线程是对的,还是多线程是对的,还是都不对。 2. 确认是读的环节错了,还是计算的环节错了,还是归并的环节错了。
闭门车 2016-09-01
  • 打赏
  • 举报
回复
第二个问题已找到

public static void sort(int[] top, String[] topKey, String key, int tmp) {
        int i = 9;
        while (i >= 0 && tmp >= top[i]) {
            i--;
        }
        if (i < 9) {
            top[i + 1] = tmp;
            topKey[i + 1] = key;
        }
    }
改为

public static void sort(int[] top, String[] topKey, String key, int tmp) {
        int i = 9;
        while (i >= 0 && tmp >= top[i]) {
            i--;
        }
        if (i < 9) {
            top[i + 1] = tmp;
            topKey[i + 1] = key;
        }
    }
但是感觉数据应该进行重排序才行,再去改下
闭门车 2016-09-01
  • 打赏
  • 举报
回复
引用 2 楼 Q80470101 的回复:
nohup.out文件给提交一份?
文件有点大,几百兆,我放百度云盘上试下,一会儿发链接
闭门车 2016-09-01
  • 打赏
  • 举报
回复
第一个问题已找到

while ((lineTxt = bufferedReader.readLine()) != null) {
                        datas.add(bufferedReader.readLine());
 
                        // System.out.println(lineTxt);
                    }
改为

while ((lineTxt = bufferedReader.readLine()) != null) {
                        datas.add(lineTxt );
 
                        // System.out.println(lineTxt);
                    }
继续找
家里敷泥呀 2016-09-01
  • 打赏
  • 举报
回复
nohup.out文件给提交一份?
闭门车 2016-09-01
  • 打赏
  • 举报
回复
没人理呢?等待达人解答

62,625

社区成员

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

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