Java 多线程读取同一文件/奇数行为

Java 多线程读取同一文件/奇数行为,java,multithreading,Java,Multithreading,我正在编写一个程序,需要从一个非常大的文件(400K+行)中读取行,并将每行中的数据发送到web服务。我决定尝试线程化,并看到了一些我没有预料到的行为,似乎我的BufferedReader开始重用我调用readline()时已经给我的行 我的课程由两个班组成。一个“Main”类,它启动线程并保存对BufferedReader的静态引用,并具有一个静态同步的“readNextLine()”方法,线程可以使用该方法基本上调用BufferedReader上的readLine()。以及调用readNex

我正在编写一个程序,需要从一个非常大的文件(400K+行)中读取行,并将每行中的数据发送到web服务。我决定尝试线程化,并看到了一些我没有预料到的行为,似乎我的BufferedReader开始重用我调用readline()时已经给我的行

我的课程由两个班组成。一个“Main”类,它启动线程并保存对BufferedReader的静态引用,并具有一个静态同步的“readNextLine()”方法,线程可以使用该方法基本上调用BufferedReader上的readLine()。以及调用readNextLine()并使用每个readNextLine()调用的数据进行webservice调用的“Runnable”类。我将BufferedReader和readNextLine()设置为静态,只是因为这是线程共享读取器的唯一方法,除了将我的主类的实例传递给线程之外,我不确定哪个更好

大约5分钟后,我开始在我的web服务中看到错误,说它正在处理已经处理过的行。我能够确认线路确实被发送了多次,间隔几分钟

有没有人知道为什么BufferedReader似乎给出了它已经读取的线程行?我的印象是readline()是连续的,我需要做的就是确保对readline()的调用是同步的

我将在下面展示一些主要的类代码。runnable本质上是一个while循环,它调用readNextLine()并处理每一行,直到没有多余的行为止

主要类别:

 //showing reader and thread creation
 inputStream = sftp.get(path to file);
 reader = new BufferedReader(new InputStreamReader(inputStream));

 ExecutorService executor = Executors.newFixedThreadPool(threads);
        Collection<Future> futures = new ArrayList<Future>();
        for(int i=0;i<threads;i++){
        MyRunnable runnable = new   MyRunnable(i);
            futures.add(executor.submit(runnable));
        }
        LOGGER.debug("futures.get()");
        for(Future f:futures){
            f.get();  //use to wait until all threads are done 
        }

public synchronized static String readNextLine(){
    String results = null;
    try{
        if(reader!=null){
         results = reader.readLine();
        }
    }catch(Exception e){
        LOGGER.error("Error reading from file");
    }

    return results;
}
//显示读卡器和线程创建
inputStream=sftp.get(文件路径);
reader=新的BufferedReader(新的InputStreamReader(inputStream));
ExecutorService executor=Executors.newFixedThreadPool(线程);
集合期货=新的ArrayList();

对于(int i=0;i我正在测试您所说的,但是我发现您的readNextLine()方法中有一个错误逻辑,当结果为null且if条件为it not null时,如何调用reader.readLine()

现在我完成了我的演示,它似乎工作得很好,下面是演示,没有发生重读行:

 static BufferedReader reader;

public static void main(String[] args) throws FileNotFoundException, ExecutionException, InterruptedException {
    reader = new BufferedReader(new FileReader("test.txt"));
    ExecutorService service = Executors.newFixedThreadPool(3);
    List<Future> results = new ArrayList<Future>();
    for (int i = 0; i < 3; i++) {
        results.add(service.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    String line = null;
                    while ((line = readNextLine()) != null) {
                        System.out.println(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }));
    }
}

public synchronized static String readNextLine() throws IOException {
    return reader.readLine();
}
静态缓冲读卡器;
公共静态void main(字符串[]args)抛出FileNotFoundException、ExecutionException、InterruptedException{
reader=newbufferedreader(newfilereader(“test.txt”);
ExecutorService=Executors.newFixedThreadPool(3);
列表结果=新建ArrayList();
对于(int i=0;i<3;i++){
results.add(service.submit(new Runnable()){
@凌驾
公开募捐{
试一试{
字符串行=null;
而((line=readNextLine())!=null){
系统输出打印项次(行);
}
}捕获(IOE异常){
e、 printStackTrace();//要更改catch语句的主体,请使用文件|设置|文件模板。
}
}
}));
}
}
公共同步静态字符串readNextLine()引发IOException{
返回reader.readLine();
}

我认为您需要使用
RandomAccessFile
并从不同的偏移量读取每个线程,尽管我会使用单个线程读取文件块,并且对于每个读取的块,分离多个线程以与您的Web服务联系部分块。实际上我刚刚偶然发现了这一点,我认为它可能会做您正试图做的事情如果Java7是一个选项,请执行此操作。