我有一个巨大的 CSV 文件,包含超过 700K 行。我必须解析该 CSV 文件的行并执行操作。我想到通过使用线程来做到这一点。我首先尝试做的事情很简单。每个线程都应该处理 CSV 文件的唯一行。我只能读取 3000 行。我创建了三个线程。每个线程应该读取 CSV 文件的一行。以下是代码:
import java.io.*;
class CSVOps implements Runnable
{
static int lineCount = 1;
static int limit = 3000;
BufferedReader CSVBufferedReader;
public CSVOps(){} // Default constructor
public CSVOps(BufferedReader br){
this.CSVBufferedReader = br;
}
private synchronized void readCSV(){
System.out.println("Current thread "+Thread.currentThread().getName());
String line;
try {
while((line = CSVBufferedReader.readLine()) != null){
System.out.println(line);
lineCount ++;
if(lineCount >= limit){
break;
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
readCSV();
}
}
class CSVResourceHandler
{
String CSVPath;
public CSVResourceHandler(){ }// default constructor
public CSVResourceHandler(String path){
File f = new File(path);
if(f.exists()){
CSVPath = path;
}
else{
System.out.println("Wrong file path! You gave: "+path);
}
}
public BufferedReader getCSVFileHandler(){
BufferedReader br = null;
try{
FileReader is = new FileReader(CSVPath);
br = new BufferedReader(is);
}
catch(Exception e){
}
return br;
}
}
public class invalidRefererCheck
{
public static void main(String [] args) throws InterruptedException
{
String pathToCSV = "/home/shantanu/DEV_DOCS/Contextual_Work/invalid_domain_kw_site_wise_click_rev2.csv";
CSVResourceHandler csvResHandler = new CSVResourceHandler(pathToCSV);
CSVOps ops = new CSVOps(csvResHandler.getCSVFileHandler());
Thread t1 = new Thread(ops);
t1.setName("T1");
Thread t2 = new Thread(ops);
t1.setName("T2");
Thread t3 = new Thread(ops);
t1.setName("T3");
t1.start();
t2.start();
t3.start();
}
}
CSVResourceHandler 类简单地查找传递的文件是否存在,然后创建一个 BufferedReader 并给出它。该读取器被传递到 CSVOps 类。它有一个方法 readCSV,可以读取 CSV 文件的一行并打印出来。限制设置为 3000。
现在,为了让线程不会弄乱计数,我将这些 limit 和 count 变量声明为静态。当我运行这个程序时,我得到奇怪的输出。我只得到大约 1000 条记录,有时我得到 1500 条。它们是随机顺序的。在输出结束时,我得到两行 CSV 文件,当前线程名称是 main!
我是一个线程新手。我希望能够快速读取此 CSV 文件。能做什么呢?
好吧,首先,不使用多个线程从单个机械磁盘执行并行 I/O。它实际上会降低性能,因为每次线程有机会运行时,机械头都需要寻找下一个读取位置。因此,您不必要地弹跳磁盘磁头,这是一项成本高昂的操作。
使用单生产者多消费者模型来使用单个线程读取行并使用工作池处理它们。
关于你的问题:
您实际上不应该在退出 main 之前等待线程完成吗?
public class invalidRefererCheck
{
public static void main(String [] args) throws InterruptedException
{
...
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)