4

Javaでファイルを読み取るスレッドを作成しています。2 つのスレッドを作成すると、各スレッドはファイル全体を読み取りますが、ファイルの異なる部分を読み取る必要があります。sleep()、join()、yield() を入れてみましたが、それらを含めた後は読み取りが遅くなります。

public class MyClass implements Runnable {

    Thread thread;
    public MyClass(int numOfThreads) {
        for(int i=0;i < numOfThreads; i++) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        readFile();
    }
}

readFile では、while ループ (1 行ずつ読み取る) で、sleep()/yield() を呼び出しました。スレッドがファイルの異なる部分を読み取れるようにするにはどうすればよいですか?

ファイルの読み取りに使用されるメソッドで更新されました...

public synchronized void readFile() {
    try {
        String str;
        BufferedReader buf = new BufferedReader(new FileReader("read.txt");
        while ((line = buf.readLine()) != null) {
            String[] info = str.split(" ");
            String first name = info[0];
            String second name = info[1];
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }  catch (IOException e) {
        System.out.println("Error : File not found");
        e.printStackTrace();
    }
}
4

2 に答える 2

25

このように複数のスレッドでファイルを読み取る方が、1 つのスレッドで読み取るよりも高速であると考えていると思います。これはほぼ間違いなく誤りです。スレッドは、複数のコアまたはプロセッサを使用して、CPU バウンド タスクのパフォーマンスを向上させます。ただし、ファイルの読み取りは CPU バウンドのタスクではありません。

OS は、ディスク コントローラを使用して、ディスク インターフェイスの全帯域幅でバイトを読み取ります。ほぼすべてのハードウェアの組み合わせで、速度は、CPU ではなく、ディスク (読み取りおよび/またはシーク時間)、そのコントローラー、およびその DMA インターフェイスまたはバスによって制限されます。CPU がディスク コントローラを 100% ビジー状態に保つのは簡単です。異なるディスクに複数のコントローラを使用する場合でも同様です。これを証明する必要がある場合は、大きなファイルのコピーを開始し、CPU 使用率を監視してください。さほど高くはないでしょう。

したがって、複数のスレッドのうち、一度に実行されるのは 1 つだけであり、シングルスレッドの計算にオーバーヘッドが追加されます。

ファイル転送が遅いのはバッファリングです。柔軟性を得るために、I/O ライブラリは各文字を 2 回または 3 回バッファリングすることになります。

Java NIO ライブラリは、このオーバーヘッドを可能な限りなくすことを目的としています。たとえば、この記事を参照してください。似たようなものはたくさんあります。私の経験では、慎重に作成された NIO リーダーは、ハードウェアの利用可能なパフォーマンスのほとんどを使用します。

注意点が 1 つあります。読み取り中の種類のファイルをスキャンするように強力なウイルス チェッカーを設定している場合、読み取りが CPU バウンドになる可能性があります。この異常なケースでは、チェッカーのアーキテクチャによっては、マルチスレッド化によってブーストが得られる可能性があります。この場合、合計ファイル サイズ S を見つけて、スレッド k=0,1,..,n-1 にオフセット kS/n から (k+1)S/n - 1 まで読み取らせます (seek右側に ing を使用)。各スレッドで読み取られたバイト数のオフセットとトラッキング)。しかし、ヘッド シーク時間の増加やランダム アクセスのその他の影響により、ウイルス チェッカーを複数のスレッドで実行するメリットが相殺されるのではないかと私は強く思っています。

于 2013-09-24T02:28:15.253 に答える
-1

プログラムで string.split(" ") を使用すると、実行速度が遅くなる可能性があります。自分で書くと、速度が6倍向上します。このようなものが役立ちます:

int index = vcf_record_string.indexOf("\t");
vcf_record_string.substring(0, index)

システムが高スループット I/O をサポートしている場合、これを行う方法は次のとおりです: 高スループット (3GB/秒) ファイル システムが使用可能な場合に、Java で複数のスレッドを使用してファイルを読み取る方法

于 2016-11-04T22:18:59.610 に答える