今儿在服务器上处理了一个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);
}
}
}
}
}