当前位置:网站首页>Runnable是否可以中断
Runnable是否可以中断
2022-07-07 13:20:00 【我不勤奋v】
背景:楼主在项目开发中遇到一个问题,在Activity中需要起一个子线程执行耗时任务,Activity退出onDestroy后,释放资源。刚好子线程执行耗时任务的时候需要访问被释放的资源,进而发生了空指针异常的崩溃。
原因:主线程和子线程是并发的,主线程Activity何时退出释放资源,子线程何时访问资源,两者时序不可控。
1)加锁可以吗?
主线程Activity退出 释放资源时候加锁,;子线程执行Runnable时加锁,并且子线程执行任务之前判断是否已经释放资源。
这样可能会导致ANR问题:万一子线程耗时任务很久,主线程退出Activity时由于锁被子线程持有一直等待,有ANR风险。
2) 不加锁,使用volatile关键字标记是否释放变量
主线程退出Activity时,volatile变量 设置为true代表已经释放。子线程的runnable 执行之前判断volatile变量的值,如果为true代表资源是否,不再执行。
上线后依旧有零星崩溃上报:子线程的runnable判断volatile变量时候,资源还没释放。执行后续的逻辑,资源释放了造成崩溃。
时序: 子线程判断volatile变量,通过——主线程释放资源——子线程后续的逻辑访问资源
于是楼主想到,主线程退出Activity时,应该释放生命周期内使用的资源,包括子线程的Runnable,让Runnable不执行或者中断。——但是真的可以中断吗?
- 有人说Handler的removeCallbacksAndMessages——对于未执行的Runnable,可以,但是对于已经跑起来的Runnable, 不行。
- 有人说Thread.interrupt, 但是interrupt仅仅起到通知被停止线程的作用,实际上对于被停止的线程而言,它拥有完全的自主权,它既可以选择立即停止,也可以选择一段时间后停止,也可以选择压根不停止。——这个是Java 不提供强制停止线程机制。
- 有人说线程池的shutdownNow方法,但是shtdownNow方法本质也还是给正在执行的线程发送interrupt。
- 有人说使用线程池的Submit(Runnable runnable) 返回一个Future, 最后通过Future的cancel方法不就可以了??——楼主亲测,跑起来的Runnable 还是不行。
以上尝试,使用如下Demo验证, Activity Destroy后,Runnable依旧执行......
public class TestActivity extends Activity {
private Runnable runnable;
private HandlerThread handlerThread;
private Handler handler;
private Thread thread;
private Future future;
private ExecutorService executorService;
private Handler mainHandler = new Handler(Looper.getMainLooper());
public static void startActivity(Context context) {
Intent intent = new Intent(context, TestActivity.class);
context.startActivity(intent);
}
private void init() {
runnable = new Runnable() {
@Override
public void run() {
while (true) {
try{
Thread.sleep(1000);
Log.e("testing", "runnable run...." + TestActivity.this);
} catch (Exception e) {
Log.e("testing", "e run...." + e.toString());
}
}
}
};
//1. handlerThread
// handlerThread = new HandlerThread("test-handler-thread");
// handlerThread.start();
// handler = new Handler(handlerThread.getLooper());
// handler.post(runnable);
//2. Thread
// thread = new Thread(runnable);
// thread.start();
//3. future
executorService = Executors.newSingleThreadExecutor();
future = executorService.submit(runnable);
}
private void release() {
//1.handlerThread
// handlerThread.quit();
// handler.removeCallbacks(runnable);
//2. Thread
// try {
// thread.interrupt();
// } catch (Exception e) {
// }
//3. future
if(future != null) {
boolean ret = future.cancel(true);
executorService.shutdown();
Log.e("testing", "future cancel...." + ret);
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Log.e("testing", "act onCreate ");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
init();
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TestActivity.this.finish();
}
});
}
@Override
protected void onDestroy() {
release();
Log.e("testing", "act onDestroy ");
super.onDestroy();
}
}
实际上,JAVA 推荐了使用Thread.currentThread().isInterrupted()的方法判断线程是否中断
也就是Demo中Runnable的 while(true) 修改为while(!Thread.currentThread().isInterrupted())
就Demo而言,可以实现中断Runnable, 但是实际项目的Runnable并不是一直循环,大多是一个耗费时间的任务。 Thread.currentThread().isInterrupted()判断不能一直贯穿整个Runnable, 只能在某一个时刻调用——万一在Runnable里调用isInterrupted()的时候线程还没interrupt, 调用isInterrupted()判断过后线程才interrupt, runnable仍然访问被释放的资源。
边栏推荐
- 用于增强压缩视频质量的可变形卷积密集网络
- Read PG in data warehouse in one article_ stat
- How bad can a programmer be? Nima, they are all talents
- Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)
- Promoted to P8 successfully in the first half of the year, and bought a villa!
- Niuke real problem programming - day13
- Novel Slot Detection: A Benchmark for Discovering Unknown Slot Types in the Dialogue System
- Andriod --- JetPack :LiveData setValue 和 postValue 的区别
- Classification of regression tests
- [Yugong series] go teaching course 005 variables in July 2022
猜你喜欢
Niuke real problem programming - day20
CTFshow,信息搜集:web13
Niuke real problem programming - Day17
CTFshow,信息搜集:web7
[server data recovery] data recovery case of raid failure of a Dell server
Window环境下配置Mongodb数据库
【數據挖掘】視覺模式挖掘:Hog特征+餘弦相似度/k-means聚類
Discussion on CPU and chiplet Technology
Ctfshow, information collection: web7
Typescript release 4.8 beta
随机推荐
Cocoscreator operates spine for animation fusion
【深度学习】语义分割实验:Unet网络/MSRC2数据集
微信小程序 01
MongoDB数据库基础知识整理
[deep learning] semantic segmentation experiment: UNET network /msrc2 dataset
Lidar knowledge drops
Zhiting doesn't use home assistant to connect Xiaomi smart home to homekit
15、文本编辑工具VIM使用
What is the process of ⼀ objects from loading into JVM to being cleared by GC?
Niuke real problem programming - Day17
简述keepalived工作原理
CTFshow,信息搜集:web4
[机缘参悟-40]:方向、规则、选择、努力、公平、认知、能力、行动,读3GPP 6G白皮书的五层感悟
Bye, Dachang! I'm going to the factory today
众昂矿业:萤石继续引领新能源市场增长
@Introduction and three usages of controlleradvice
【OBS】RTMPSockBuf_Fill, remote host closed connection.
Excerpted words
Spatiotemporal deformable convolution for compressed video quality enhancement (STDF)
Connecting FTP server tutorial