0

我正在用 Java 编写一个我想暂停和恢复的多线程应用程序。
线程正在逐行读取文件,同时查找与模式匹配的行。它必须在我暂停线程的地方继续。为了读取文件,我将 BufferedReader 与 InputStreamReader 和 FileInputStream 结合使用。

fip = new FileInputStream(new File(*file*));
fileBuffer = new BufferedReader(new InputStreamReader(fip));

我使用这个 FileInputStream 因为我需要文件指针作为文件中的位置。
在处理这些行时,它将匹配的行写入 MySQL 数据库。要在线程之间使用 MySQL 连接,我使用 ConnectionPool 来确保只有一个线程正在使用一个连接。

问题是当我暂停线程并恢复它们时,一些匹配的行就消失了。我还尝试从偏移量中减去缓冲区大小,但它仍然存在同样的问题。

什么是解决这个问题的好方法或者我做错了什么?

更多细节:

循环

    // Regex engine
    RunAutomaton ra = new RunAutomaton(this.conf.getAuto(), true);
    lw = new LogWriter();

        while((line=fileBuffer.readLine()) != null) {
            if(line.length()>0) {
                if(ra.run(line)) {
                        // Write to LogWriter
                        lw.write(line, this.file.getName());
                        lw.execute();
                    }
                }
            }
            // Loop when paused.
            while(pause) { }
        }

计算文件中的位置

// Get the position in the file
public long getFilePosition() throws IOException {
    long position = fip.getChannel().position() - bufferSize + fileBuffer.getNextChar();
    return position;
}

将其放入数据库

            // Get the connector
            ConnectionPoolManager cpl = ConnectionPoolManager.getManager();
            Connector con = null;
            while(con == null)
                con = cpl.getConnectionFromPool();
            // Insert the query
            con.executeUpdate(this.sql.toString());
            cpl.returnConnectionToPool(con);
4

3 回答 3

2

这是我认为您正在寻找的示例。您没有展示太多的实现,因此很难调试可能导致您出现差距的原因。请注意, 的位置将FileInputStream是 8192 的倍数,因为BufferedReader正在使用该大小的缓冲区。如果您想使用多个线程来读取同一个文件,您可能会发现这个答案很有帮助。

public class ReaderThread extends Thread {
    private final FileInputStream fip;
    private final BufferedReader fileBuffer;
    private volatile boolean paused;

    public ReaderThread(File file) throws FileNotFoundException {
        fip = new FileInputStream(file);
        fileBuffer = new BufferedReader(new InputStreamReader(fip));
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }

    public long getFilePos() throws IOException {
        return fip.getChannel().position();
    }

    public void run() {
        try {
            String line;
            while ((line = fileBuffer.readLine()) != null) {
                // process your line here
                System.out.println(line);

                while (paused) {
                    sleep(10);
                }
            }
        } catch (IOException e) {
            // handle I/O errors
        } catch (InterruptedException e) {
            // handle interrupt
        }
    }
}
于 2011-04-22T08:55:16.070 回答
1

我认为问题的根源在于您不应该减去bufferSize. 相反,您应该减去缓冲区中未读字符的数量。而且我不认为有办法得到这个。

我能想到的最简单的解决方案是创建一个 FilterReader 的自定义子类,以跟踪读取的字符数。然后按如下方式堆叠流:

FileReader 
< BufferedReader 
< custom filter reader
< BufferedReader(sz == 1)

finalBufferedReader在那里,以便您可以使用 readLine ... 但您需要将缓冲区大小设置为 1,以便过滤器中的字符数与应用程序到达的位置相匹配。

或者,您可以在自定义过滤器阅读器中实现自己的readLine()方法。

于 2011-04-22T09:46:07.557 回答
0

经过几天的搜索,我发现确实减去缓冲区大小并添加缓冲区中的位置并不是正确的方法。位置从来都不是正确的,我总是漏掉一些台词。
在寻找一种新的工作方式时,我没有计算字符数,因为字符数太多了,这会大大降低我的表现。但我发现了别的东西。软件工程师 Mark S. Kolich 创建了一个 JumpToLine 类,它使用 Apache IO 库跳转到给定的行。它还可以提供它读到的最后一行,所以这确实是我需要的。
他的主页上有一些例子供感兴趣的人参考。

于 2011-05-05T03:18:44.370 回答