Java Android线程分配-堆增长?
大家好 在我使用需要重新启动的活动时,我正在开发一个针对API 7的android应用程序。假设我的活动如下所示:Java Android线程分配-堆增长?,java,android,multithreading,heap,Java,Android,Multithreading,Heap,大家好 在我使用需要重新启动的活动时,我正在开发一个针对API 7的android应用程序。假设我的活动如下所示: public class AllocActivity extends Activity implements OnClickListener{ Button but; private Handler hand = new Handler(); @Override protected void onCreate(Bundle savedInstan
public class AllocActivity extends Activity implements OnClickListener{
Button but;
private Handler hand = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_alloc);
but = (Button) findViewById(R.id.button);
but.setText("RELOAD");
but.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0){
Intent intent = getIntent();
startActivity(intent);
finish();
}
});
}
@Override
protected void onDestroy(){
super.onDestroy();
System.gc();
}
/****** THREADS AND RUNNABLES ******/
final Runnable fullAnim = new Thread(new Runnable(){
@Override
public void run(){
try{
hand.post(anim1);
Thread.sleep(2000);
hand.post(anim2);
Thread.sleep(1000);
// and so on
}catch(InterruptedException ie){ie.printStackTrace();}
}
});
final Runnable anim1 = new Runnable() {
@Override
public void run(){
// non-static method findViewById
ImageView sky = (ImageView)findViewById(R.id.sky);
}
};
}
Thread t = new Thread(fullAnim);
t.start();
问题是gc似乎没有释放fullAnim线程,因此堆在每次重新启动时都会增加约100K,直到它变慢并崩溃。将fullAnim声明为静态确实解决了这个问题,但由于我使用非静态引用,这对我来说并不可行
所以在这一点上我有点迷路了,我希望你能给我建议下一步该去哪里。是否有我可能做错的事情,或者是否有一个工具可以用来管理线程,以便在重新启动后丢弃和释放堆
亲切问候
更新
感谢每一个回答的人——帮助了很多。使用TimerTask最终成功了。我做了以下改变:
/****** THREADS AND RUNNABLES ******/
final TimerTask fullAnim = new TimerTask(){
@Override
public void run(){
try{
hand.post(anim1);
Thread.sleep(2000);
hand.post(anim2);
Thread.sleep(1000);
// and so on
}catch(InterruptedException ie){ie.printStackTrace();}
}
};
由于活动长度超过6k loc,这是一个相当不错的解决方案,不会面临更大的影响。荣誉
我不使用计时器来安排任务-不知道这是否是一种不好的做法,但是
动画的名称如下所示:
public class AllocActivity extends Activity implements OnClickListener{
Button but;
private Handler hand = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_alloc);
but = (Button) findViewById(R.id.button);
but.setText("RELOAD");
but.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0){
Intent intent = getIntent();
startActivity(intent);
finish();
}
});
}
@Override
protected void onDestroy(){
super.onDestroy();
System.gc();
}
/****** THREADS AND RUNNABLES ******/
final Runnable fullAnim = new Thread(new Runnable(){
@Override
public void run(){
try{
hand.post(anim1);
Thread.sleep(2000);
hand.post(anim2);
Thread.sleep(1000);
// and so on
}catch(InterruptedException ie){ie.printStackTrace();}
}
});
final Runnable anim1 = new Runnable() {
@Override
public void run(){
// non-static method findViewById
ImageView sky = (ImageView)findViewById(R.id.sky);
}
};
}
Thread t = new Thread(fullAnim);
t.start();
与任何JavaVM一样,堆内存将自动增长到最大大小。但是,位图是在虚拟机之外分配的,因此您不容易在统计信息中看到它们。最好的办法是确保不要使用大型位图,或者使用 当您在安卓1.6或更高版本上时,可以从Eclipse生成堆转储,并且可以使用EclipseMat分析转储 通常,您无法控制实际设备上的最大堆大小,除非您使用自定义硬件或固件 developer.android.com上应该有一篇关于在1.6上转储堆的文章,但我找不到它: 编辑 另外,我必须提到,您可以通过使用
android:largeHeap="true"
在舱单上。但这是非常不明智的,因为大多数应用程序不需要它。因为最终变量对GC的优先级较低。因此,您需要在onPause方法中显式释放可运行对象,因为无法确保OnDestroy在完成调用后立即调用
@Override
protected void onPause(){
super.onPause();
//cancel timer to stop animations
if(t!=null){
t.cancel();
}
System.gc();
}
更新
使用定时器来实现这一点
boolean isFirstAnim=true;
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
if(isFirstAnim){
// play your first animation at every
}else{
// play your second animation at every
}
}
}, 0, 3000);
运行的线程永远不会被垃圾收集。
如果活动停止或被破坏,线程不会自动停止。它可以永远运行。
每个非静态内部类都保留对封闭实例的引用。例如,手摇1;在该内部类中工作,因为它具有对AllocActivity.this的隐式引用。
因此,有效的做法是将活动的引用保持在比预期的活动时间更长的时间内,即直到onDestroy之后
如果您不再需要它们,请确保手动执行
当您调用finish时,这并不意味着活动实例是
垃圾收集。你告诉安卓你想关闭
活动不再显示它。它将一直存在,直到
Android决定终止进程,从而终止DVM或
实例被垃圾收集
您需要实现自己的停止方法来停止正在运行的线程,您可以在onDestroy中调用它
参考此
或者
您可以在asynctask中执行操作,并使用onProgressUpdate在UI线程上发布进度,使用canceltrue与check in doInBackground结合使用是否已调用cancel来停止任务。ya我了解到使用大型位图可能会导致分配问题,但即使我没有在线程/可运行项。。对于本例-fullAnim可能完全为空,但其中没有任何内容-堆仍将增长我尝试使用编写的示例活动-堆仍在增长:/您可以使用的另一种选择是计时器和TimerTask。您可以在销毁时取消计时器。