1

Web サイトに接続して Web ページのタイトルを取得するプログラムを作成しました。プログラムに挿入できるテキストから URL を取得すると、すべての URL がリストに表示されます。速度を上げるために、複数のスレッドを使用します。たとえば、10 個のスレッドと 10 個の URL がある場合、プログラムは約 100 MB のメモリを使用します。しかし、5 つのスレッドと 10 の URL がある場合、各スレッドが 2 つの Web サイトに接続する必要があるため、メモリ使用量は最大で約 1.3 GB になります。私のプログラムが非常に多くのメモリを使用するのは、コード内の1行であることがわかりました。

in = new BufferedReader(new InputStreamReader(spoof.getInputStream()));

これはこの方法にあります:

private BufferedReader in;
private URL url;
private URLConnection spoof;

private void openConnection() {

    try {
        url = new URL(tag.url);
        spoof = url.openConnection();
        spoof.setRequestProperty("User-Agent", userAgent);

        in = new BufferedReader(new InputStreamReader(spoof.getInputStream()));

    } catch (IOException ex) {
        tag.ableToConnect = false;
    }
}

BufferedReader を閉じてマニュアルを実行しようとしましたSystem.gc()。どちらもメモリ使用量には影響しません。

お役に立てれば幸いです。ありがとう!

4

3 に答える 3

2

たとえば、10 個のスレッドと 10 個の URL がある場合、プログラムは約 100 MB のメモリを使用します。

いくつかの一般的なコメント。

  1. BufferedReader任意の時点で10 個 (または 100 個) のオブジェクトが存在していても問題はありません。デフォルトのバッファ サイズは 8k 文字または 16k バイトです。それらの100は数メガになります。各スレッドは一度に 1 つずつ読み取る必要があり、 の場合でもメモリを適切に解放するために、ブロック内の に設定するBufferedReader必要があります(以下を参照) 。close()nullintry {} finally {}IOException

  2. メモリリークが実際にあるBufferedReader場合は、明らかにそれらへの参照を何らかの形で保持しています。基礎となるバッファーを解放しないため、それを呼び出すclose()だけでは十分ではありません。GCが確実に取得できるように、in参照されるフィールドとその他の場所を設定する必要があります。nullたぶん、保持しているクラスはBufferedReaderコレクションか何かに保持されていますか?

  3. 考慮すべきことの 1 つは、キュー内の未処理の URL の数を制限することです。URL キューがどれだけ大きくなるかがわかると、キュー自体に保持されているメモリの量がわかります。String代わりにURLまたはもっと重いものをキューに入れることを検討するかもしれません。キューのサイズを制限すると、スレッドがページを処理できなくなり、デッドロックが発生する可能性があるため、完全には機能しません。

于 2013-11-03T15:39:57.787 に答える
0

1) inputstreamreader を試してください 2) 行ごとに読み取られたすべてのチャンクを読み取ろうとしないでください

public class BufferedReaderExample {   

    public static void main(String args[]) {

        //reading file line by line in Java using BufferedReader       
        FileInputStream fis = null;
        BufferedReader reader = null;

        try {
            fis = new FileInputStream("C:/sample.txt");
            reader = new BufferedReader(new InputStreamReader(fis));

            System.out.println("Reading File line by line using BufferedReader");

            String line = reader.readLine();
            while(line != null){
                System.out.println(line);
                line = reader.readLine();
            }           

        } catch (FileNotFoundException ex) {
            Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);

        } finally {
            try {
                reader.close();
                fis.close();
            } catch (IOException ex) {
                Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
  } 

続きを読む: http://javarevisited.blogspot.com/2012/07/read-file-line-by-line-java-example-scanner.html#ixzz2jVVs2RMN 速度に問題があることが判明した場合は、ご覧ください。 [java.nio][1] パッケージで - これらはおそらく java.io よりも高速です。

于 2013-11-02T16:42:55.517 に答える
-1

それが役立つかどうかはわかりませんが、InputStreamReader も閉じる必要があります。

于 2013-11-02T16:42:15.303 に答える