一个快速的理论问题。假设我有一个Java类,它使用了终结器和它自己的私有AsyncTask的实例,而不是在其他任何地方引用它。
现在假设AsyncTask的doInBackground方法类似于:
while(go) {
f();
}
,终结者是:
public void finalize() {
go = false;
}
当删除对该对象的所有外部引用时,是否会停止AsyncTask?或者系统是否继续使用该线程,从不删除该对象,因为它是由线程引用的?
答案 0 :(得分:2)
我可以依靠垃圾收集器来停止AsyncTask吗?
不,你不能。实际上,您可以依靠GC NOT 停止任务。
GC只会完成一个无法访问的对象。但是根据定义,所有活动线程都可以访问,这意味着AsyncTask
对象也可以访问。
答案 1 :(得分: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...
正如您所看到的,线程未停止,即使其任务完全是私有的,并且不再对其容器对象进行任何外部引用。
答案 2 :(得分:0)
我认为AsyncTask永远不会停止,因为你在go = false;
循环中执行此操作:while
。只有当go
条件在循环内变为false
时,该循环才会停止。如上所述执行循环,go
条件永远不会更新,而while循环只会检查go
变量的初始状态。看看this问题。
右边循环的example:
class WhileDemo {
public static void main(String[] args){
int count = 1;
while (count < 11) {
System.out.println("Count is: "
+ count);
count++;
}
}
}
这不会是无限循环,因为我们正在改变循环中的while条件。 您还可以使用break语句以正确的方式退出循环。
另一个考虑因素。如果AsyncTask
被标记为守护程序线程,则当删除对该对象的所有外部引用时,系统应该停止该线程。有关守护程序线程here和here的更多详细信息。