Android一个APP里面最少有几个线程

news2024/11/24 16:08:09

Android一个APP里面最少有几个线程

参考

https://www.jianshu.com/p/92bff8d6282f
https://www.jianshu.com/p/8a820d93c6aa

线程查看

Android一个进程里面最少包含5个线程,分别为:

  1. main线程(主线程)
  2. FinalizerDaemon线程
    终结者守护线程。对于重写了成员函数finalize的对象,它们被GC决定回收时,并没有马上被回收,而是被放入到一个队列中,等待FinalizerDaemon守护线程去调用它们的成员函数finalize,然后再被回收。
  3. FinalizerWatchdogDaemon线程
    监控终结者守护线程。用来监控FinalizerDaemon线程的执行。一旦检测那些重定了成员函数finalize的对象在执行成员函数finalize时超出一定的时候,那么就会退出VM。
  4. HeapTaskDaemon线程
    堆栈守护线程。用来执行堆栈的操作,也就是用来将那些空闲的堆内存归还给系统。
  5. ReferenceQueueDaemon线程。
    引用队列守护线程。我们知道,在创建引用对象的时候,可以关联一个队列。当被引用对象引用的对象被GC回收的时候,被引用对象就会被加入到其创建时关联的队列去。这个加入队列的操作就是由ReferenceQueueDaemon守护线程来完成的。这样应用程序就可以知道哪些被引用对象引用的对象已经被回收了。

下图是创建的一个仅有hello World!页面的工程,线程包含以下的这些。

在这里插入图片描述

刚开始我比较疑惑的是FileObserver 这个线程是否也是每个进程所必须包含的线程。后来我查看了一下Daemons创建的过程,能确定的是Android启动一个APP最少包含ReferenceQueueDaemon线程、FinalizerDaemon线程、FinalizerWatchdogDaemon线程、HeapTaskDaemon线程,以及在ActivityThread中开启的主线程。如下:

public final class Daemons {
    private static final int NANOS_PER_MILLI = 1000 * 1000;
    private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
    private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND;

    public static void start() {
        ReferenceQueueDaemon.INSTANCE.start();//开启ReferenceQueueDaemon线程
        FinalizerDaemon.INSTANCE.start();//开启FinalizerDaemon线程
        FinalizerWatchdogDaemon.INSTANCE.start();//开启FinalizerWatchdogDaemon线程
        HeapTaskDaemon.INSTANCE.start();//开启HeapTaskDaemon线程
    }

    public static void startPostZygoteFork() {
        ReferenceQueueDaemon.INSTANCE.startPostZygoteFork();
        FinalizerDaemon.INSTANCE.startPostZygoteFork();
        FinalizerWatchdogDaemon.INSTANCE.startPostZygoteFork();
        HeapTaskDaemon.INSTANCE.startPostZygoteFork();
    }

    public static void stop() {
        HeapTaskDaemon.INSTANCE.stop();
        ReferenceQueueDaemon.INSTANCE.stop();
        FinalizerDaemon.INSTANCE.stop();
        FinalizerWatchdogDaemon.INSTANCE.stop();
    }
    ...
}

1.main线程

2. ReferenceQueueDaemon线程。

代码块

3. FinalizerDaemon线程

    private static class FinalizerDaemon extends Daemon {
        private static final FinalizerDaemon INSTANCE = new FinalizerDaemon();
        private final ReferenceQueue<Object> queue = FinalizerReference.queue;
        private final AtomicInteger progressCounter = new AtomicInteger(0);
        // Object (not reference!) being finalized. Accesses may race!
        private Object finalizingObject = null;

        FinalizerDaemon() {
            super("FinalizerDaemon");
        }

        @Override public void runInternal() {
            // This loop may be performance critical, since we need to keep up with mutator
            // generation of finalizable objects.
            // We minimize the amount of work we do per finalizable object. For example, we avoid
            // reading the current time here, since that involves a kernel call per object.  We
            // limit fast path communication with FinalizerWatchDogDaemon to what's unavoidable: A
            // non-volatile store to communicate the current finalizable object, e.g. for
            // reporting, and a release store (lazySet) to a counter.
            // We do stop the  FinalizerWatchDogDaemon if we have nothing to do for a
            // potentially extended period.  This prevents the device from waking up regularly
            // during idle times.

            // Local copy of progressCounter; saves a fence per increment on ARM and MIPS.
            int localProgressCounter = progressCounter.get();

            while (isRunning()) {
                try {
                    // Use non-blocking poll to avoid FinalizerWatchdogDaemon communication
                    // when busy.
                    FinalizerReference<?> finalizingReference = (FinalizerReference<?>)queue.poll();
                    if (finalizingReference != null) {
                        finalizingObject = finalizingReference.get();
                        progressCounter.lazySet(++localProgressCounter);
                    } else {
                        finalizingObject = null;
                        progressCounter.lazySet(++localProgressCounter);
                        // Slow path; block.
                        FinalizerWatchdogDaemon.INSTANCE.goToSleep();
                        finalizingReference = (FinalizerReference<?>)queue.remove();
                        finalizingObject = finalizingReference.get();
                        progressCounter.set(++localProgressCounter);
                        FinalizerWatchdogDaemon.INSTANCE.wakeUp();
                    }
                    doFinalize(finalizingReference);
                } catch (InterruptedException ignored) {
                } catch (OutOfMemoryError ignored) {
                }
            }
        }

        @FindBugsSuppressWarnings("FI_EXPLICIT_INVOCATION")
        private void doFinalize(FinalizerReference<?> reference) {
            FinalizerReference.remove(reference);
            Object object = reference.get();
            reference.clear();
            try {
                object.finalize();
            } catch (Throwable ex) {
                // The RI silently swallows these, but Android has always logged.
                System.logE("Uncaught exception thrown by finalizer", ex);
            } finally {
                // Done finalizing, stop holding the object as live.
                finalizingObject = null;
            }
        }
    }

4. FinalizerWatchdogDaemon线程

代码块

5. HeapTaskDaemon线程

private static class HeapTaskDaemon extends Daemon {
        private static final HeapTaskDaemon INSTANCE = new HeapTaskDaemon();

        HeapTaskDaemon() {
            super("HeapTaskDaemon");
        }

        // Overrides the Daemon.interupt method which is called from Daemons.stop.
        public synchronized void interrupt(Thread thread) {
            VMRuntime.getRuntime().stopHeapTaskProcessor();
        }

        @Override public void runInternal() {
            synchronized (this) {
                if (isRunning()) {
                  // Needs to be synchronized or else we there is a race condition where we start
                  // the thread, call stopHeapTaskProcessor before we start the heap task
                  // processor, resulting in a deadlock since startHeapTaskProcessor restarts it
                  // while the other thread is waiting in Daemons.stop().
                  VMRuntime.getRuntime().startHeapTaskProcessor();
                }
            }
            // This runs tasks until we are stopped and there is no more pending task.
            VMRuntime.getRuntime().runHeapTasks();
        }
    }

查看VMRuntime的源码发现 startHeapTaskProcessor()、runHeapTasks()均是native方法。

    public native void requestConcurrentGC();
    public native void concurrentGC();
    public native void requestHeapTrim();
    public native void trimHeap();
    public native void startHeapTaskProcessor();
    public native void stopHeapTaskProcessor();
    public native void runHeapTasks();

如何查看当前项目包含几个线程

在Android studio中点击Profile 图标,点击 CPU,显示如下图,点击 Record,然后再点击 Stop,即可生成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pg 视图

1.概念 2.创建 3.修改 3.删除 4.递归

【量子计算】开辟全新计算范式

1. &#x1f680; 引言1.1 &#x1f680; 量子计算的现状与发展趋势1.2 &#x1f4dc; 量子位、量子门和量子电路的基本概念1.3 &#x1f3c6; 量子计算在科学研究中的作用 2. &#x1f50d; 量子计算的演变与创新2.1 &#x1f31f; 量子计算的发展历程2.2 &#x1f9e0; 量子算…

Dit架构 diffusion范式分类+应用

1.ping 网址 2.ssh nscc/l20 3.crtl,打开vscode的setting 4.win 10修改ssh配置文件及其密钥权限为600 - 晴云孤魂 - 博客园 整体来看&#xff1a; 使用transformer作为其主干网络&#xff0c;代替了原先的UNet 在latent space进行训练&#xff0c;通过transformer处理潜…

Leetcode——数组:二分搜索法704.二分查找相似题目

知识点&#xff1a; 二分搜索的区间&#xff0c;一般分为左闭右闭或左闭右开 left0 易错点1 while(易错点2) {middle(leftright)/2if(nums[middle]>target){right易错点3}else if(nums[middle]<target){leftmiddle1}else if(nums[middle]target){return target} } retu…

NRF52832

当我下载完NRF的芯片包后出现了一个缺失pack的问题 解决方法&#xff1a; CMSIS缺失警告_error #541: arm::cmsis:core:4.3.0 component is m-CSDN博客 引入新的型号的芯片问题总结&#xff1a; 一般引入新的型号的芯片都会涉及到.pack和芯片包的问题 外设调用&#xff1a; …

论文阅读:LLaVA-OneVision: Easy Visual Task Transfer

论文地址&#xff1a;https://arxiv.org/pdf/2408.03326 公开时间&#xff1a;2024年9月14日 项目地址&#xff1a;https://llava-vl.github.io/blog/llava-onevision LLaVA-OneVision是一个开放的大型多模态模型&#xff08;LMMs&#xff09;&#xff0c;它是通过整合在LLaVA…

【星闪开发连载】SLE_UUID_Server和SLE_UUID_Client程序分析

引言 星闪测试已经搁置了很久了&#xff0c;主要是8-9月份太忙了。今天重新捡回来。想看看官方提供的星闪例子&#xff0c;在application\samples\bt\sle\sle_uuid_client\和sle_uuid_server目录。这两个例子是一对&#xff0c;一个用来广播服务&#xff0c;另一个去连接。对应…

Mybatis-plus的基础用法

文章目录 1. 核心功能1.1 配置与编写规则1.2 条件构造器1.3 自定义SQL1.4 IService接口1.4.1 Lambda方法1.4.2 批量新增 1.5 分页查询 2. 拓展功能2.1 代码生成器2.2 DB静态工具2.3 逻辑删除2.4 枚举处理器 参考 1. 核心功能 1.1 配置与编写规则 Maven依赖&#xff1a; <…

Autosar EcuM配置-初始化及下电执行函数-基于ETAS软件

文章目录 前言EcuMCommonConfigurationEcuMDriverInitListOneEcuMModuleIDEcuMModuleParameterEcuMModuleServiceEcuMRbDriverInitCoreIdEcuMDriverInitListZeroEcuMGeneralEcuMRbOnGoOffOneCalloutEcuMRbCalloutFunctionEcuMRbModuleIDEcuMRbServiceIsNonAutosarEcuMRbOnGoOff…

java控制台输出乱码

第一步&#xff1a;修改 IntelliJ IDEA 全局编码、项目编码、属性文件编码 File->Settings… Editor->File Encodings(不要忘记点击Apply然后OK) 第二步&#xff1a;修改当前 Web 项目 Tomcat Server 的虚拟机输出选项 Run->Edit Configurations… 复制代码->…

DBMS-3.2 SQL(2)——DML的SELECT(含WHERE、聚集函数、GROUP BY、HAVING之间的关系)

本文章的素材与知识来自李国良老师和王珊老师。 数据操纵语言DML&#xff08;Data Manipulation Language&#xff09; SELECT 一.SELECT的语法与构成 1.语法 2.构成 二.投影 投影操作可以选择表中的若干列&#xff0c;主要体现在SELECT子句后的列表达式。 1.列表达式 2.…

【书生浦语实战】茴香豆企业级知识库问答工具-搭建Dify问答助手

快速结论 1、用茴香豆快速搭建Dify问答助手&#xff0c;自带拒答、rerank、切片长度判断、阈值调节功能&#xff0c;回答还能带出图片&#xff0c;顶呱呱&#x1f44d; 2、茴香豆git仓地址&#xff1a;https://github.com/internlm/huixiangdou 遇到问题去翻这里会更多解释&…

如何利用免费音频剪辑软件制作出精彩音频

现在有许多免费的音频剪辑软件可供选择&#xff0c;它们为广大用户提供了丰富的功能和便捷的操作体验&#xff0c;让音频编辑变得更加轻松和有趣。接下来&#xff0c;让我们一起走进这些免费音频剪辑软件的世界&#xff0c;探索它们的独特魅力和强大功能。 1.福昕音频剪辑 链…

李宏毅深度学习-图神经网络GNN

图卷积的开源代码网站DGL 好用的还是 GAT, GIN&#xff08;指出最好的卷积 就是 hi 邻居特征&#xff08;而且只能用 sum&#xff09;&#xff09; Introduction GNN 可以理解为是由 Graph&#xff08;图) Nerual Networks 组合而成的&#xff0c;图结构应该都在数据结构与…

No.12 笔记 | 网络基础:ARP DNS TCP/IP与OSI模型

一、计算机网络&#xff1a;安全的基石 1. 网络的本质&#xff1a;数字世界的神经系统 定义&#xff1a;计算机的互联互通&#xff0c;实现资源共享和信息交换组成要素&#xff1a;发送者、接收者、介质、数据、协议&#xff08;五大要素&#xff09; 2. 网络架构&#xff1…

STM32PWM应用

一、输出比较(OC) OC&#xff08;Output Compare&#xff09;输出比较 可以通过比较CNT与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形每个高级定时器和通用定时器都拥有4个输出比较通道高级定时器的前…

三菱FX3U定位控制接线示例(脉冲控制伺服)

一、FX3u系列基本单元(DC24V输入) 二、FX3u系列基本单元(晶体管输出) 脉冲输出用端子Y000、 Y001、 Y002为高速响应输出。 三、FX3UPLC链接MR-J4-A伺服连接实例 1、为了安全起见&#xff0c;不仅仅在可编程控制器侧&#xff0c;在伺服放大器侧也请设计正转限位和反转限位的限位…

查缺补漏----拥塞窗口

注意事项1&#xff1a; 首先区分超时和收到3个冗余ACK&#xff0c;显然超时更加严重。如下图所示&#xff1a; 如果网络出现超时&#xff0c;那么发送窗口cwnd变为1&#xff0c;门限值ssthresh变为原来拥塞窗口的一半 如果收到3个冗余ACK&#xff0c;发送窗口cwnd门限值ssth…

Java重修笔记 第六十一天 坦克大战(十一)IO 流 - 节点流和处理流、BufferedReader 和 BufferedWriter

节点流和处理流的区别和联系 1. 节点流是底层流/低级流&#xff0c;直接和数据源联系 2. 处理流是经过包装过后的节点流&#xff0c;也叫包装流&#xff0c;既可以消除不同节点流的实现差异&#xff0c;也可以提供更方便的方法来完成输入输出 3. 处理流&#xff08;包装流&…

二叉树基本概念讲解

一.树的概念 1.概念 树是⼀种非线性的数据结构&#xff0c;它是由 n&#xff08;n>0&#xff09;个有限结点组成⼀个具有层次关系的集合。把它叫 做树是因为它看起来像⼀棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有⼀个特殊的结点&#xff0c…