3

これは簡単な質問ではないと思います。手短に、何が起こっているかの小さな例を挙げます。Byron.txt ファイルにデータ ソースがあるとします。


彼女は雲のない気候と星空の夜のように、美しさの中を歩きます。
そして、暗くて明るい最高のもの
彼女の側面と彼女の目で会いましょう:華やか な日に天国が否定
するその優しい光にとてもまろやかです.

そして、このコードは AsyncTask 内で実行されます。

final ArrayList<Record> poem = new ArrayList<Record>();
final Object objectLock = new Object();
private Record rec = new Record();

@Override
protected Void doInBackground(Void... args) {
    String line = null;
    int i;
    int last;

    try {
        process = Runtime.getRuntime().exec("cat Byron.txt");
        bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 8192);

        synchronized (objectLock) {
            poem.clear();
            last = i = poem.size() - 1;
        }
        while(line = bufferedReader.readLine()) != null) {
            rec.setString(line);
            synchronized (objectLock) {
                last++;
                poem.add(last, rec);
            }

            while(!bPause && i < last) {
                i++;
                publishProgress(poem.get(i));
            }
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

@Override
protected synchronized void onProgressUpdate(Record... m) {
    if(m.length > 0) {
        mContext.mTable.appendRow(m[0]);
    }

}

UI に TableLayout があり、新しい行を取得するたびに新しい TableRow を追加します。これは、UI に表示される出力です。


彼女は雲のない気候と星空の夜のように、美しさの中を歩きます。
雲ひとつない気候と星空。
雲ひとつない気候と星空。
優しい光に
まろやかに やさしい光にまろやかに

デバッガーを起動すると、なぜそれが起こるのかがわかります。がスキップされ、ループが続く
場合があります。すでにキャッチ済み のため公開はありません。 その後、ブロックはスキップされた回数だけ実行されます が、元の行が失われ、代わりに現在の行が数回追加されます。 その後、すべての新しい行が再びキャッチされるまで公開されます。synchronized (objectLock)
ilast

poem
ilast

コードに従っていることがわかり、何が起こっているのかを説明できます。ここでの質問は、ブロックがスキップされるのはなぜですか?
同期ブロックが実行可能になるまで停止すると予想していました。
少なくともこれは、synchronized (objectLock)
使用しなくてもの機能を理解した方法でwait()あり、notify()

ここでディスカッションを開くふりはしません (必要に応じて、チャット エリアでディスカッションを開くこともできます)
。コードに問題がある場合は、質問に答えてお知らせください。

ノート:

  1. synchronizedアプリ内の別の場所で、ユーザーがこれまでに取得した行をメールで送信したい場合があるため、必要です。
  2. ユーザーは公開を一時停止できます ( bpause)。それがwhileループで、が falseの場合にのみi続きます。lastbPause
4

2 に答える 2

3

答えを公開することにしました。その単純さにとても恥ずかしく思いますが。クラスやメッセージ処理などについて
深く掘り下げた後で初めて、私はそれを発見しました。AsyncTask

人々が結論に飛びつく前に基本的なことをチェックするのに役立ち、誰かがこの投稿のおかげで半日デバッグを節約できることを願って、私はそれを公開します.

Record rec毎回同じでした。poemArrayList は、各エントリに対して同じ要素 ID を持っていました。そして、それらはすべて同じだったので、内容は一度にすべて変更されました。
進行状況がすぐに公開されると、最後の文字列である正しい文字列が出力されました。ただし、何らかの遅延により進行状況が後で公開される場合、poem.get(i)レコードを取得すると、別のエントリが取得されますが、同じポインターを持つため、同じコンテンツが取得されます。

解決策は、ループごとに新しいレコードを作成することでした。

于 2012-05-20T17:03:11.187 に答える
0

オブジェクトの同期を行いlastます。

synchronized (last) {
   last++;
   poem.add(last, line);
}
于 2012-05-20T05:43:18.150 に答える