Android中通过子线程修改Activity状态失效且白屏重启如何解决
问题原因
- 子线程无限死循环占用CPU:
MyThread的run方法包含无退出条件的while(true)循环,启动后会持续占用CPU资源,导致负责UI渲染和事件响应的主线程无法获得足够调度资源,最终触发ANR(应用无响应),表现为白屏、闪退重启。 - 重复创建线程:每次点击按钮都会新建一个线程执行死循环任务,点击次数越多CPU占用越高,会加速系统杀进程的触发。
- 内存泄漏:
MyThread持有ActivityTwo的强引用,只要线程没有终止,就算ActivityTwo被销毁也无法被GC回收,持续占用内存,资源耗尽时也会导致应用崩溃。
解决方案
- 给循环增加退出条件:新增运行状态标记,在
Activity销毁时终止线程,避免无限运行。 - 使用弱引用持有Activity实例:避免因为线程持有强引用导致的内存泄漏。
- 避免重复启动线程:增加线程运行状态判断,防止多次点击创建多个死循环线程。
- 保证多线程数据可见性:给
myValue增加volatile修饰,保证子线程修改的值在主线程能正常读取。
修正后代码
MyThread类
public class MyThread implements Runnable { // 用弱引用持有Activity,避免内存泄漏 private WeakReference<ActivityTwo> activityRef; // 运行状态标记,volatile保证多线程状态可见 public volatile boolean isRunning = true; public MyThread(ActivityTwo activity) { this.activityRef = new WeakReference<>(activity); } @Override public void run() { // 增加退出条件 while(isRunning){ ActivityTwo activity = activityRef.get(); // Activity已经被回收直接退出线程 if(activity == null) { break; } activity.setValue(2); // 若不需要高频修改,可增加休眠降低CPU占用,示例: // try { Thread.sleep(100); } catch (InterruptedException e) { break; } } } }
ActivityTwo类
public class ActivityTwo extends AppCompatActivity { private MyThread myThread; private Button startLogBtn; // volatile保证多线程下的变量可见性 private volatile int myValue; // 标记线程是否已启动,避免重复创建 private boolean threadStarted = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); startLogBtn = findViewById(R.id.startLogBtn); myThread = new MyThread(this); startLogBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 避免重复启动线程 if(!threadStarted) { new Thread(myThread).start(); threadStarted = true; } } }); } @Override protected void onDestroy() { super.onDestroy(); // Activity销毁时主动终止线程释放资源 if(myThread != null) { myThread.isRunning = false; } } public void setValue(int value){ this.myValue= value; } }
内容的提问来源于stack exchange,提问作者Lakshan Weerasinghe
相关产品推荐
相关产品推荐

