4

簡単な理論上の質問。ファイナライザーと、他のどこにも参照されていない独自のプライベート AsyncTask のインスタンスの両方を使用する Java クラスがあるとします。

ここで、AsyncTask の doInBackground メソッドが次のようなものであるとします。

while(go) {
 f();
}

ファイナライザーは次のとおりです。

public void finalize() {
 go = false;
}

オブジェクトへのすべての外部参照が削除されると、AsyncTask は停止しますか? それとも、スレッドによって参照されているため、システムはオブジェクトを削除せずにスレッドを続行しますか?

4

3 に答える 3

2

AsyncTask を停止するためにガベージ コレクターに頼ることはできますか?

いいえ、できません。実際、GCがタスクを停止しないことを信頼できます。

GC は、到達不能になったオブジェクトのみをファイナライズします。ただし、すべてのアクティブなスレッドは定義上到達可能です。つまり、AsyncTaskオブジェクトも到達可能になります。

于 2012-08-19T05:22:16.037 に答える
1

簡単な答え: スレッドは進行し続けます。GC に依存して停止することはできません。

詳細: 私の質問に対する十分な回答を得ることができませんでした (ただし、Alberto に感謝します)。私はこれを経験的に自分でテストすることにしました。次のテスト コードを使用します。

public class TestActivity extends Activity {
   private ThreadContainer mtc;

   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);

      mtc = new ThreadContainer();
   }

   public void btnFree_click(View view) {
      Log.v("TestActivity","Free clicked");
      mtc = null;
   }
}

public class ThreadContainer {
   private boolean go = true;

   public ThreadContainer() {
      new testThread().execute(1);
   }

   private class testThread extends AsyncTask<Integer,Integer,Integer> {
      protected Integer doInBackground(Integer... arg0) {
        while(go) {
          Log.v("testThread","I'm running...");

          try {
            Thread.sleep(500);
          } catch (InterruptedException e) {
            // do nothing
          }
       }

     return 0;
      }
  }

  @Override
  public void finalize() {
      go = false;
  }
}

logcat から次の出力を取得できました。

I/ActivityManager(  244): Displayed com.example.test/.TestActivity: +509ms
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/TestActivity(13728): Free clicked
D/dalvikvm(  512): GC_EXPLICIT freed 144K, 50% free 2891K/5767K, external 1685K/2133K, paused 164ms
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
D/dalvikvm(13449): GC_EXPLICIT freed 12K, 47% free 2894K/5379K, external 1685K/2133K, paused 94ms
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...
V/testThread(13728): I'm running...

スレッドのタスクが完全にプライベートであり、コンテナー オブジェクトへの外部参照がなくなっているにもかかわらず、スレッドが停止していないことがわかります。

于 2012-08-19T05:08:48.697 に答える
0

あなたはこれをやっているので、 AsyncTask は決して停止しないと思います : go = false;whileループ外。そのループは、ループ内でgo条件が に変化した場合にのみ停止します。false上記のようにループを実行するgoと、条件は更新されず、while ループはgo変数の初期状態のみをチェックします。このSOの質問を見てください。

右 while ループの例:

class WhileDemo {
    public static void main(String[] args){
        int count = 1;
        while (count < 11) {
            System.out.println("Count is: "
                               + count);
            count++;
        }
    }
}

ループ内で while 条件を変更しているため、これは無限ループにはなりません。breakステートメントを使用して、正しい方法でループを終了することもできます。

別の考慮事項。がデーモン スレッドとしてマークされている場合AsyncTask、オブジェクトへのすべての外部参照が削除されると、システムはスレッドを停止する必要があります。デーモン スレッドの詳細については、こちらこちらをご覧ください。

于 2012-08-18T12:42:36.230 に答える