android - 如何在 Android Studio 中杀死线程
问题描述
目标:我想在应用程序处于后台时增加计数器,当应用程序现在处于恢复状态时,增量应该停止,然后计数器的最后一个值将显示在屏幕上。
实际:但是当我运行我的代码时,如果应用程序在后台,计数器会成功递增。但是当我恢复时,计数器仍在增加。如果它现在在恢复中,我该如何停止这个线程?
这是我在 MainActivity.java 中的代码
package com.example.background;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView timeTextView;
Button buttonCtr;
int counter=0;
boolean isResume;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timeTextView = (TextView) findViewById(R.id.timeLbl);
buttonCtr = (Button) findViewById(R.id.ctrUp);
buttonCtr.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
counter++;
timeTextView.setText(String.valueOf(counter));
}
});
}
class backgroundProcess extends Thread {
@Override
public void run() {
while(isResume == false ) {
counter++;
System.out.println(counter);
}
System.out.println("LAST COUNT:" + counter);
}
}
@Override
protected void onPause() {
super.onPause();
isResume=false;
System.out.println("IM IN PAUSE");
System.out.println("IS RESUME: "+ isResume);
new Thread(new backgroundProcess()).start();
}
@Override
protected void onRestart() {
super.onRestart();
isResume=true; //to stop backgroundProcess Thread
System.out.println("IM IN RESUME");
System.out.println("IS RESUME: "+ isResume);
System.out.println("LAST COUNT:"+ counter);
timeTextView.setText(String.valueOf(counter));
}
}
这是我的 xml 文件的代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/timeLbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.482"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.397" />
<Button
android:id="@+id/ctrUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="196dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.475"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/timeLbl"
app:layout_constraintVertical_bias="0.54" />
</androidx.constraintlayout.widget.ConstraintLayout>
解决方案
2件事,在这里:
您没有使用任何同步原语。这意味着后台线程的读取
isResume
是不可靠的;它可能会出现在后台线程中isResume
,false
即使 UI 线程已经将其设置为true
. 在这种特殊情况下,您应该能够声明isResume
为volatile
,这将消除缓存一致性问题。您正在以极高的速度将信息转储到 logcat,可能每秒数十万行 (
System.out.println(counter)
)。Android Studio 无法以这样的速度读取和显示 logcat 信息。在这种情况下,它通常会滞后,这可能导致您的线程看起来正在运行,即使它已经停止。
我还应该提到您的访问counter
不是线程安全的。与 不同isResume
的是,您正在从两个线程++
上执行读/写操作 ( ) ,因此该关键字不足以修复。您必须确保所有访问都受到实际锁的保护(例如,通过将它们包装在一个块中)。counter
volatile
counter
synchronized(MainActivity.this)
推荐阅读
- python-3.x - 如何在 IF 语句的上下文中使用 Python Pandas isin()
- mysql - 使用外键 SQL 向表中插入数据
- c - 我可以通过 C 中的 sprintf 更改文本颜色吗?
- android - CoordinatorLayout 中的 ViewPager(用于粘性标题)导致滚动中断
- ruby - 同步两个日历?
- python - 计算毕达哥拉斯定理的一面,使用函数
- haskell - 为什么不能在 Haskell 中使用没有 'let..in' 块的 'Just' 语法?
- python - Matplotlib 未保存所有绘图
- ffmpeg - FFMPEG 我可以获取每帧的音频音量级别以在表达式中使用吗?
- sql - 添加摘要行时如何在没有第二列的情况下进行 GROUP BY ROLLUP