无法通过if语句停止线程问题求助(附相关代码)
解决线程无法通过if语句停止的问题
首先看你的代码,核心问题出在这几个地方:
- 死循环没有退出出口:
while (true)是个无限循环,哪怕你的if条件满足了某些终止逻辑,也没有代码能跳出这个循环,线程会一直跑下去。 - 共享变量的可见性问题:
firstTextDigit、secondTextDigit这些变量如果是类的成员变量,没有用volatile修饰的话,你的线程可能看不到其他线程(比如UI线程)修改后的最新值,导致if判断永远达不到你预期的条件。 - 终止逻辑不完整:你在UI线程里的
if (secondTextDigit == 9)块里写了semaphore.release...但没写完,而且就算写完了,也没有通知线程退出循环的逻辑。
下面是修改后的完整代码,我会标注关键改动:
class SecondTextViewTask extends Thread { // 1. 添加volatile的线程停止标志位,保证多线程下的可见性 private volatile boolean isRunning = true; // 假设这两个变量是类成员,同样加上volatile保证可见性 private volatile int firstTextDigit; private volatile int secondTextDigit; private Semaphore semaphore; private TextView secondDigit; private WeakReference<Activity> activityRef; // 用弱引用持有Activity,避免内存泄漏 // 构造函数传入需要的变量 public SecondTextViewTask(Semaphore semaphore, TextView secondDigit, Activity activity, int firstTextDigit, int secondTextDigit) { this.semaphore = semaphore; this.secondDigit = secondDigit; this.activityRef = new WeakReference<>(activity); this.firstTextDigit = firstTextDigit; this.secondTextDigit = secondTextDigit; } @Override public void run() { // 2. 把while(true)改成while(isRunning),用标志位控制循环 while (isRunning) { if (semaphore.availablePermits() == 0 && firstTextDigit <= 9 && secondTextDigit <= 9) { try { Thread.sleep(1000); Activity activity = activityRef.get(); if (activity == null) { // Activity已销毁,直接停止线程 isRunning = false; break; } activity.runOnUiThread(new Runnable() { @Override public void run() { secondTextDigit++; secondDigit.setText(String.valueOf(secondTextDigit)); Log.e("Test== ", "" + secondTextDigit + " " + semaphore.availablePermits()); if (secondTextDigit == 9) { // 补全semaphore的release逻辑,比如释放许可 semaphore.release(); // 3. 当满足终止条件时,设置isRunning为false,让线程退出循环 isRunning = false; } } }); } catch (InterruptedException e) { // 4. 处理线程中断异常,这里也可以设置isRunning为false,保证线程能退出 isRunning = false; Thread.currentThread().interrupt(); // 保留中断状态 e.printStackTrace(); } } // 加个小延迟,避免空转占用过多CPU try { Thread.sleep(100); } catch (InterruptedException e) { isRunning = false; Thread.currentThread().interrupt(); e.printStackTrace(); } } Log.e("Test== ", "SecondTextViewTask线程已停止"); } // 5. 提供外部调用的停止方法,方便主动终止线程 public void stopTask() { isRunning = false; this.interrupt(); // 中断可能在sleep的线程,让它尽快退出 } }
关键改动说明:
- volatile标志位:
isRunning用volatile修饰,确保主线程或其他线程修改这个值时,当前线程能立刻看到最新值,不会因为线程缓存导致判断失效。 - 替换无限循环:用
while(isRunning)替代while(true),让线程可以通过修改标志位优雅停止,而不是强制终止。 - 处理InterruptedException:当线程在sleep时被中断,会抛出这个异常,我们需要在catch块里设置
isRunning=false,保证线程能退出循环。 - 外部停止方法:提供
stopTask()方法,方便外部主动调用停止线程,比如在Activity的onDestroy里调用,避免内存泄漏。 - 共享变量可见性:
firstTextDigit和secondTextDigit也加上volatile,确保线程能看到最新的变量值,你的if判断才能正确生效。 - 弱引用持有Activity:避免因线程持有Activity强引用导致的内存泄漏问题。
另外还要注意:Semaphore的使用要保证逻辑闭环,比如什么时候获取许可、什么时候释放,避免出现死锁或许可耗尽的情况。
内容的提问来源于stack exchange,提问作者ZpCikTi
相关产品推荐
相关产品推荐

