大数据下多线程对文件的检索

今儿在服务器上处理了一个30G+的文件,把Xmx飚到了128000m,感觉一般般,现把代码贴出来,借以抛砖引玉

1、开辟1000个线程操作3.6E数据对其进行检索,为保证负载均衡,999个线程每个线程读N/999大小的数据块,第1000个线程读不足数据块大小的数据

代码不难,就直接代码了。

编写工具类:

package com.zgf;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class BigUtilThread {
    public int getLine(String path) throws IOException{
        BufferedReader br=null;
        br=new BufferedReader(new FileReader(path),10*1024*1024);//缓存10M  1G=1024*1024*1024
        String str=""; 
        int line=0;
        while((str=br.readLine())!=null){
            line++;
        }
        br.close();
        return line;
    }
    //加载到内存
    public String[] LoadFile(String path,int num) throws IOException{
        BufferedReader br=null;
        String[] myspaces;
        myspaces=new  String[num]; 
        System.out.println("load start");
        try {
            br=new BufferedReader(new FileReader(path),10*1024*1024);//缓存10M
            String str=null; 
            int line=0;
            while((str=br.readLine())!=null){
                myspaces[line]=str;
                line++;
//                if(line%1000_0000==0){
//                    System.out.println("line="+line);
//                }
            }
            br.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("load end");    
        return myspaces;
    }
    
    //单线程实现
    public void searchdata(String data,String [] arr){
        for(String mystr:arr){    //查找
            if(mystr.contains(data)){
                System.out.println(mystr);
            }
        }
    }
    
//  多线程实现--使用的是线程池     第一个for循环变量控制线程;第二个for循环变量控制每个线程应该读到的内存数组的下标范围
//    为了使每个线程负载均衡:999个线程每个线程读N/999大小的数据块,第1000个线程读不足数据块大小的数据
    public void searchdataMoreThread(String data,String arr[]){//参数是用户输入的数据,
        ExecutorService pool=Executors.newFixedThreadPool(1000);
        Future<?> future=null;
        final int N=arr.length;
        final int M=N/999;    //1000个线程工作,999平分,余下的给第1000个线程执行
        //999个线程工作
        for(int i=0;i<1000-1;i++){    
            final int idata=i;    //lambdac必须是final  idata把i进行final化
            future=pool.submit(()->{
                for(int j=idata*M;j<(idata+1)*M;j++){
                    if(arr[j].contains(data)){
                        System.out.println(Thread.currentThread().getId()+"  "+arr[j]);
                    }
                }
            });
        }
        //第1000个线程工作
        future=pool.submit(()->{
            final int MM=N/999*999;    //第1000个线程 要开始工作数据的下标,
            for(int j=MM;j<N;j++){
                if(arr[j].contains(data)){
                    System.out.println(Thread.currentThread().getId()+"  "+arr[j]);
                }
            }
        });
    }
    
}

测试类如下:

package com.zgf;

import java.io.IOException;

import javax.swing.JOptionPane;

//把数据加载到内存,开启1000个线程,保证负载均衡  
//可以读任意大的文件,当读的文件很大时,可以调节BufferedReader的缓冲区为1G=1024*1024*1024
public class Thread1000MEM {
    public static void main(String[] args) throws IOException {
        
        String path="F:\\dataSort.txt";
        BigUtilThread util=new BigUtilThread(); 
        int line=util.getLine(path);
        String arr[]=util.LoadFile(path,line);
        
        int i=0;
        while(true){ //奇数次进行单线程查找,偶数次进行多线程查找  
            String str=JOptionPane.showInputDialog("请输入要查询的内容");
            
            if(i%2==0){
                util.searchdata(str,arr);
            }else{
                util.searchdataMoreThread(str,arr);
            }
            i++;
        }
        
    }
}
2、多线程基于磁盘的查找---每个线程处理一个文件  ---读一行判断一次

public class Demo2 {

	public static void main(String[] args) throws InterruptedException {
		String paths="D:\\网易3.6G";
		String str=JOptionPane.showInputDialog("请输入要查询的内容");
		File file=new File(paths);
		File[] allfile=file.listFiles();
		int num=allfile.length;	 //文件个数
		Thread [] ths=new Thread[num];
		for(int i=0;i<num;i++){
			final File nowfile=allfile[i];
			ths[i]=new Thread( ()->{
				try {
					BufferedReader br=new BufferedReader(new FileReader(nowfile.getAbsoluteFile()),10*1024*1024);
					String readstr="";
					while((readstr=br.readLine())!=null){
						if(readstr.contains(str)){
							 System.out.println(Thread.currentThread().getId()+"  "+readstr);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			});
			
			ths[i].join();
		}
		
		for(int i=0;i<num;i++){
			ths[i].start();
		}
	}

}
3、多线程加载到内存  ----每个线程处理一个文件
注:不是内存数组,是LinkedList<LinkedList<String>>

读到LinkedList中解析:

如果读到String[num][]二维数组,其一维数组当读每个文件时要再分配大小;

读到ArrayList<ArrayList<String>>中,其底层使用的是数据,数组的插入性能低。综合考虑使用LinkedList

public static void main(String[] args) throws InterruptedException {
	String paths="D:\\网易数据3.6G";
	File file=new File(paths);
	File[] allfile=file.listFiles();
	int num=allfile.length;
	Thread[] ths=new Thread[num];
	LinkedList<LinkedList<String>> allstr=new LinkedList<LinkedList<String>>();
	for(int i=0;i<num;i++){
		final File nowfile=allfile[i];	// 第i个文件类型的路径
		ths[i]=new Thread( ()->{
			LinkedList<String> mystr=new LinkedList<String>();
			try {
				BufferedReader br=new BufferedReader(new FileReader(nowfile.getAbsoluteFile()),10*1024*1024);
				String readstr="";
				while((readstr=br.readLine())!=null){
					mystr.add(readstr);		//一个线程一个
				}
				allstr.add(mystr);			//所有线程共享一个
				System.out.println(Thread.currentThread().getId()+"  over");
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		
		ths[i].start();
		ths[i].join();
	}
	
	while(true){
		String str=JOptionPane.showInputDialog("请输入要查询的数据");
		for(LinkedList<String> lsstr:allstr){
			for(String findstr:lsstr){
				if(findstr.contains(str)){
					System.out.println(findstr);
				}
			}
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值