安卓开发中遇到的奇奇怪怪的问题(三)

// 直接调用stop方法,在Android 6.0之前会有线程安全问题
final Method method = clazz.getSuperclass().getDeclaredMethod(“stop”);
method.setAccessible(true);
method.invoke(watchdog);
} catch (final Throwable e) {
Log.e(TAG, “stopWatchDog, stop occur error:” + t);
t.printStackTrace();
}
}
} catch (final Throwable t) {
Log.e(TAG, “stopWatchDog, get object occur error:” + t);
t.printStackTrace();
}

其实我是用的是stackoverflow这篇帖子中提供的方法:

public static void fix() {
try {
Class clazz = Class.forName(“java.lang.Daemons$FinalizerWatchdogDaemon”);

Method method = clazz.getSuperclass().getDeclaredMethod(“stop”);
method.setAccessible(true);

Field field = clazz.getDeclaredField(“INSTANCE”);
field.setAccessible(true);

method.invoke(field.get(null));

}
catch (Throwable e) {
e.printStackTrace();
}
}

两种方法都是通过反射最终将FinalizerWatchdogDaemon中的thread置空,这样也就不会执行此线程,所以不会再有超时异常发生。推荐老师的方法,更加全面完善。因为在Android 6.0之前会有线程安全问题,如果直接调用stop方法,还是会有几率触发此异常。5.0源代码如下:

private static abstract class Daemon implements Runnable {

private Thread thread;// 一种是直接置空thread

public synchronized void start() {
if (thread != null) {
throw new IllegalStateException(“already running”);
}
thread = new Thread(ThreadGroup.systemThreadGroup, this, getClass().getSimpleName());
thread.setDaemon(true);
thread.start();
}

public abstract void run();

protected synchronized boolean isRunning() {
return thread != null;
}

public synchronized void interrupt() {
if (thread == null) {
throw new IllegalStateException(“not running”);
}
thread.interrupt();
}

public void stop() {
Thread threadToStop;
synchronized (this) {
threadToStop = thread;
thread = null; // 一种是通过调用stop置空thread
}
if (threadToStop == null) {
throw new IllegalStateException(“not running”);
}
threadToStop.interrupt();
while (true) {
try {
threadToStop.join();
return;
} catch (InterruptedException ignored) {
}
}
}

public synchronized StackTraceElement[] getStackTrace() {
return thread != null ? thread.getStackTrace() : EmptyArray.STACK_TRACE_ELEMENT;
}
}

这个所谓的线程安全问题就在stop方法中的threadToStop.interrupt()。在6.0开始,这里变为了interrupt(threadToStop),而interrupt方法加了同步锁。

public synchronized void interrupt(Thread thread) {
if (thread == null) {
throw new IllegalStateException(“not running”);
}
thread.interrupt();
}

虽然崩溃不会出现了,但是问题依然存在,可谓治标不治本。通过这个问题也提醒我们,尽量避免重写finalize方法,同时不要在其中有耗时操作。其实我们Android中的View都有实现finalize方法,那么减少View的创建就是一种解决方法。

强烈推荐阅读提升Android下内存的使用意识和排查能力再谈Finalizer对象–大型App中内存与性能的隐性杀手

3.SchedulerPoolFactory

前一阵在用Android Studio的内存分析工具检测App时,发现每隔一秒,都会新分配出20多个实例,跟踪了一下发现是RxJava2中的SchedulerPoolFactory创建的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
一般来说如果一个页面创建加载好后是不会再有新的内存分配,除非页面有动画、轮播图、EditText的光标闪动等页面变化。当然了在应用退到后台时,或者页面不可见时,我们会停止这些任务。保证不做这些无用的操作。然而我在后台时,这个线程池还在不断运行着,也就是说CPU在周期性负载,自然也会耗电。那么就要想办法优化一下了。

SchedulerPoolFactory 的作用是管理 ScheduledExecutorServices的创建并清除。

SchedulerPoolFactory 部分源码如下:

static void tryStart(boolean purgeEnabled) {
if (purgeEnabled) {
for (;😉 { // 一个死循环
ScheduledExecutorService curr = PURGE_THREAD.get();
if (curr != null) {
return;
}
ScheduledExecutorService next = Executors.newScheduledThreadPool(1, new RxThreadFactory(“RxSchedulerPurge”));
if (PURGE_THREAD.compareAndSet(curr, next)) {

// RxSchedulerPurge线程池,每隔1s清除一次
next.scheduleAtFixedRate(new ScheduledTask(), PURGE_PERIOD_SECONDS, PURGE_PERIOD_SECONDS, TimeUnit.SECONDS);

return;
} else {
next.shutdownNow();
}
}
}
}

static final class ScheduledTask implements Runnable {
@Override
public void run() {
for (ScheduledThreadPoolExecutor e : new ArrayList(POOLS.keySet())) {
if (e.isShutdown()) {
POOLS.remove(e);
} else {
e.purge();//图中154行,purge方法可用于移除那些已被取消的Future。
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2020面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

2020面试真题解析
腾讯面试真题解析

阿里巴巴面试真题解析

字节跳动面试真题解析
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

[外链图片转存中…(img-byZtSib5-1710697061019)]

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值