0

一時停止して再開したいマルチスレッドを使用してJavaでアプリケーションを作成しています。
スレッドは、パターンに一致する行を見つけながら、ファイルを1行ずつ読み取っています。スレッドを一時停止した場所で続行する必要があります。ファイルを読み取るには、BufferedReaderをInputStreamReaderおよびFileInputStreamと組み合わせて使用​​します。

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

このFileInputStreamを使用するのは、ファイル内の位置にファイルポインターが必要だからです。
行を処理するときに、一致する行をMySQLデータベースに書き込みます。スレッド間でMySQL接続を使用するには、ConnectionPoolを使用して、1つのスレッドだけが1つの接続を使用していることを確認します。

問題は、スレッドを一時停止して再開すると、一致するいくつかの行が消えてしまうことです。また、オフセットからバッファサイズを減算しようとしましたが、それでも同じ問題が発生します。

この問題を解決するための適切な方法は何ですか、または私は何を間違っていますか?

詳細:

ループ

    // 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)

最後BufferedReaderはreadLine...を使用できるようにするためですが、フィルターからの文字数がアプリケーションが到達した位置と一致するように、バッファーサイズを1に設定する必要があります。

readLine()または、カスタムフィルターリーダーで独自のメソッドを実装することもできます。

于 2011-04-22T09:46:07.557 に答える
0

数日検索した後、実際にバッファサイズを減算してバッファ内の位置を追加することは、それを行う正しい方法ではないことがわかりました。位置は決して正しくなく、私はいつもいくつかの行を逃していました。
仕事をするための新しい方法を探すとき、文字数が多すぎてパフォーマンスが大幅に低下するため、文字数を数えませんでした。しかし、私は何か他のものを見つけました。ソフトウェアエンジニアのMarkS.Kolichは、ApacheIOライブラリを使用して特定の行にジャンプするクラスJumpToLineを作成しました。それはまたそれが読んだ最後の行を提供することができるので、これは本当に私が必要としているものです。
興味のある人のために彼のホームページにいくつかの例があります。

于 2011-05-05T03:18:44.370 に答える