线程调度(Java Android)

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。
未经允许不得转载

目录

  • 一、导读
  • 二、概览
    • 2.1、线程的属性
  • 三、线程的调度
    • 3.1 Java内存模型
    • 3.2 高速缓存
    • 3.3 Java 线程调度机制
    • 3.4 Android线程调度
  • 四、 推荐阅读

在这里插入图片描述

一、导读

我们继续总结学习基础知识,温故知新。

我们在前面讲过
【线程相关基础知识】,本文在此基础上,讲述Android线程调度的相关知识。

二、概览

线程优化是性能优化的一个重点,使用不当的话也会有很大的影响,所以我们需要清楚线程调度原理。
通过基础知识,我们知道任意时刻,只有一个线程占用CPU,处于运行状态,其他的现场处于等待状态,即使是多线程,也是如此,区别就
在于多线程并发是多个线程轮流获取CPU使用权(CPU时间片轮转机制)。

2.1、线程的属性

在日志中,我们经常可以看到这样的信息 com.xxx#RenderThread(119111), 这里面就有线程的名字及编号(id)。
线程有id、名字、类别以及优先级四个属性,我们分别列一下:

  • 编号
    线程的编号(id)用于标识不同的线程,每条线程拥有不同的编号;
    这个id不能作为线程唯一标识,某个编号的线程运行结束后,该编号可能被后续创建的线程使用,因此编号不适合用作唯一标识,编号是只读属性,不能修改;

  • 名字
    每个线程都有自己的名字(name),名字的默认值是 Thread-线程编号,比如 Thread-0 ;
    除了默认值,我们也可以给线程设置名字,以我们自己的方式去区分每一条线程;
    作用:给线程设置名字可以让我们在某条线程出现问题时,用该线程的名字快速定位出问题的地方

  • 类别
    线程的类别(daemon)分为守护线程和用户线程,我们可以通过 setDaemon(true) 把线程设置为守护线程;

  • 优先级
    线程的优先级(Priority)用于表示应用希望优先运行哪个线程,线程调度器会根据这个值来决定优先运行哪个线程;

具体可参考【线程相关基础知识】

三、线程的调度

我们先来了解一些相关概念

3.1 Java内存模型

【jvm 堆、栈、方法区 & java 内存模型】

在多线程场景下,CPU会出现缓存一致性问题,处理器重新排序问题,

为了解决这个问题,制定了计算机内存模型。(原子性、可见性、有序性)
即是Java语言对这个操作规范的遵循,

JMM规定了所有的变量都存储在主存中,每个线程都有自己的工作区,
线程将使用到的变量从主存中复制一份到自己的工作区,线程对变量的所有操作(读取、赋值等)都必须在工作区,
不同的线程也无法直接访问对方工作区,线程之间的消息传递都需要通过主存来完成。
可以把这里主存类比成计算机内存模型中的主存,工作区类比成计算机内存模型中的高速缓存。

在这里插入图片描述

3.2 高速缓存

处理器的处理能力要远胜于主内存(DRAM)的访问速率,;
为了弥补处理器与主内存之间的差距,硬件设计者在主内存与处理器之间加入了高速缓存(Cache);

CPU 高速缓存是内置于 CPU(中央处理器)或位于处理器芯片上的小型快速内存区域。CPU 高速缓存存储主内存中经常使用的数据和指令,以减少 CPU 为这些信息访问主内存的次数

高速缓存相当于是一个由硬件实现的容量极小的散列表,这个散列表的 key 是一个对象的内存地址,value 可以是内存数据的副本,也可以是准备写入内存的数据;

3.3 Java 线程调度机制

1、 在任意时刻,CPU 只能执行一条机器指令,每个线程只有获取到 CPU 的使用权后,才可以执行指令;
也就是在任意时刻,只有一个线程占用 CPU,处于运行的状态;

2、 多线程并发运行实际上是指多个线程轮流获取 CPU 使用权,分别执行各自的任务;

3、 线程的调度由 JVM 负责,线程的调度是按照特定的机制为多个线程分配 CPU 的使用权;

线程调度模型分为两类:分时调度模型和抢占式调度模型;

  • 分时调度模型
    分时调度模型是让所有线程轮流获取 CPU 使用权,并且平均分配每个线程占用 CPU 的时间片;

  • 抢占式调度模型
    让优先级高的线程占用 CPU,如果线程的优先级都一样,那就随机选择一个线程,并让该线程占用 CPU;

也就是如果我们同时启动多个线程,并不能保证它们能轮流获取到均等的时间片;
如果我们的程序想干预线程的调度过程,最简单的办法就是给每个线程设定一个优先级;

多线程是不安全的,具体参考线程的原子性、可见性、有序性及线程安全

3.4 Android线程调度

Android是基于java开发的,但是又有所改动,线程调度也是有所区别的。

Android线程调度有两个决定因素:

  1. Android应用程序线程优先级
    定义在android.os.Process类中,跟java线程优先级一样,值越小优先级越高,
/*** Standard priority of application threads.* Use with {@link #setThreadPriority(int)} and* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal* {@link java.lang.Thread} class.*/public static final int THREAD_PRIORITY_DEFAULT = 0;/*** Standard priority background threads.  This gives your thread a slightly* lower than normal priority, so that it will have less chance of impacting* the responsiveness of the user interface.* Use with {@link #setThreadPriority(int)} and* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal* {@link java.lang.Thread} class.*/public static final int THREAD_PRIORITY_BACKGROUND = 10;

我们可以在代码中直接定义线程的优先级,如:

    thread.setPriority(android.os.Process.THREAD_PRIORITY_DEFAULT);
  1. cgroup
    android中还定义了一种更严格的群组调度策略,了解linux的同学都清楚,
    Linux的cgroup(Control Group)是一种内核特性,用于对进程组进行资源限制、优先级管理和统计等操作。
    cgroup可以将一组相关的进程组织在一起,并对它们施加各种资源控制策略,以确保系统资源的有效分配和管理。

Android就是借用了这种特性的思想,我们简单理解为将进程进行了分组,比如后台进程组,将后台进程归为一个组,这个组里面的
线程在cpu忙的时候,只有比较小的概率能获取到cpu。

这种前台和后台分开执行策略,即允许后台线程执行任务,保证前台线程可以获取更多的CPU,不会对前台现场造成很大的影响,极大概率的减少卡顿。

下面的线程会移到后台group

  • 优先级低的线程;
  • 不在前台运行的线程

总结一下:
1、线程不是越多越好,太多反而影响效率,大家可参考一下:
线程切换开销
2、另外在设置优先级的时候要酌情一下,并不是都设置最高,最好根据业务情况及工作量来。
3、现场具有继承性,如A线程中启动B线程,则B线程的优先级跟A一样。

四、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

未经允许不得转载

ddd

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

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

相关文章

继承基本介绍

Java提供了关键字extends&#xff0c;可以让一个类和另一个类建立父子关系。 public class a extends b{ //b为父类&#xff0c;&#xff0c;a为子类} 继承的特点&#xff1a;子类可以继承父类的非私有成员&#xff1b;子类的对象由子类、父类共同完成 使用继承可以减少重复…

【正点原子STM32】STM32基础知识(F1F4F7H7 STM32系统框架、寻址范围、存储器映射的存储器功能划分、寄存器映射)

一、STM32系统框架 1.1、Cortex M内核 & 芯片1.2、F1系统架构1.3、F4系统架构1.4、F7系统架构1.5、H7系统架构 二、STM32的寻址范围&#xff1f; 三、存储器映射 存储器功能划分&#xff08;F1为例&#xff09;STM32F1存储器映射图 四、寄存器映射 寄存器基础知识STM3…

python-自动化篇-办公-文件-加解密

解说 要使⽤Python进⾏⽂件的加密和解密&#xff0c;可以使⽤第三⽅加密库&#xff0c;如cryptography或pycryptodome。 ⼀个基本的⽰例&#xff0c;演⽰如何使⽤cryptography库对⽂件进⾏加密和解密&#xff1a; 安装cryptography库&#xff1a; pip install cryptography⽂…

【Vue3 + Vite】Vite搭建 项目解构 Vue快速学习 第一期

文章目录 Vue3介绍Vue3通过Vite实现工程化&#xff1a;一、Vite创建Vue3工程化项目1.1 ViteVue3项目的创建、启动、停止1.2 ViteVue3项目的目录结构 二、ViteVue3 项目组件(SFC入门)2.1 什么是VUE的组件 ?2.2 什么是.vue文件 ?2.3 工程化vue项目如何组织这些组件? 三、ViteV…

【NodeJS】004- NodeJS的模块化与包管理工具

模块化 1. 介绍 1.1.什么是模块化与模块 ? 将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为 模块化 其中拆分出的 每个文件就是一个模块 ,模块的内部数据是私有的,不过模块可以暴露内部数据以便其他模块使用 1.2 什么是模块化项目 ? 编码时是按照模…

23. 集合类

集合 1. 概述2. 分类2.1 单列集合&#xff08;Collection&#xff09;2.2 双列集合&#xff08;Map&#xff09; 单列集合 Collection、List、Set、ArrayList、LinkedList’、Vector、HashSet、TreeSet、LinkedHashSet双列集合 Map、HashTable、HashMap、TreeMap、Properties、…

docker 部署及命令

一、容器概述 1、为什么要用到容器&#xff1f; ①容器可以屏蔽底层操作系统的差异性&#xff0c;让业务应用不管在哪里都是使用容器的环境运行&#xff0c;从而保证开发测试环境与生产环境的一致性 ②容器部署起来非常便捷和迅速&#xff0c;缩短开发测试部署的周期时间 2…

阅读go语言工具源码系列之gopacket(谷歌出品)----第二集 layers-巧妙的抽象与无聊的协议包

上一集中我们讲到了wpcap.dll的go封装方法&#xff0c;对于linux系统下libpcap的go封装采用的是常用的cgo方式&#xff0c;想了解的可以看看pcap文件夹中的pcap_unix.go。 我们得到了wpcap.dll的go调用&#xff0c;就可以利用它来进行列举所有网络设备&#xff0c;例如以下代码…

知识产权如何转为实缴资本,实操

网上已传疯了&#xff0c;相关部门要求企业注册资本认缴的必须在5年内完成实缴&#xff0c;这一下子引起企业老板们着急了。以前公司注册时&#xff0c;很多老板因为是认缴资本&#xff0c;完全凭脑袋一拍&#xff0c;写上注册资金5000万&#xff0c;有的甚至写上几个小目标。现…

11.Elasticsearch应用(十一)

Elasticsearch应用&#xff08;十一&#xff09; 1.什么是自动补全 现代的搜索引擎&#xff0c;一般都会提供Suggest as you type的功能 帮助用户在输入搜索的过程中&#xff0c;进行自动补全或者纠错。通过协助用户输入更加精准的关键词&#xff0c;提高后续搜索阶段文档的…

【GitHub项目推荐--开源翻译模型】【转载】

开源翻译模型 Seamless M4T 旨在提供高质量的翻译&#xff0c;使来自不同语言的人们能够轻松地通过语音和文本进行交流&#xff0c;支持 101 种语言用于语音输入、96 种文本语言输入/输出、 可以输出 35 种语音语言。 此统一模型支持多个任务&#xff0c;而不依赖于多个单独的…

漏洞原理反射型XSS漏洞

漏洞原理XSS漏洞 1 反射型XSS php基础链接 Web渗透编程语言基础-CSDN博客 正常思维 http://127.0.0.1/websec/day01/xss_reflect.php?name%E6%88%91%E6%98%AF%E8%B0%81 http://127.0.0.1/14_WEBSEC/DAY01/xss_reflect.php?name我是谁 黑客思维 http://127.0.0.1/websec…

Unity 开发过程中如何优化内存

在开发Unity游戏时&#xff0c;优化内存使用是非常重要的。这不仅可以提高游戏性能&#xff0c;还能保证游戏在各种设备上都能顺利运行。以下是一些关于如何在Unity中优化内存使用的建议&#xff1a; 1. 了解并监控您的内存使用情况&#xff1a;您可以使用Unity的Profiler工具…

echarts option series smooth

echarts option series smooth 平滑处理 smooth&#xff1a;0.3 echarts_04_line.html <!DOCTYPE html> <html lang"en"><head> <meta charset"utf-8"> <title></title> </head><body><div id&quo…

【Git版本控制】以及搭建gitlab服务

目录 一、Git介绍二、Git安装与全局配置1、git的全局配置&#xff1a;2、为常用的指令配置别名&#xff1a;3、Git初始化本地代码仓库4、Git的基础命令 三、分支四、Git远程仓库1、操作远程仓库2、从远程仓库克隆3、从远程仓库中抓取和拉取 五、Gitlab sever部署期间出现遇到的…

python爬虫demo——爬取历史平均房价

简单爬取历史房价 需求 爬取的网站汇聚数据的城市房价 https://fangjia.gotohui.com/ 功能 选择城市 https://fangjia.gotohui.com/fjdata-3 需要爬取年份的数据&#xff0c;等等 https://fangjia.gotohui.com/years/3/2018/ 使用bs4模块 使用bs4模块快速定义需要爬取的…

有趣的数学 了解TensorFlow的自动微分的实现

一、简述 这里主要介绍了TensorFlow的自动微分(autodiff)功能如何工作,以及与其他解决方案的比较。假设您定义了一个函数,并且需要计算它的偏导数和,通常用于执行梯度下降(或某些其他优化算法)。可用的主要选择是手动微分、有限差分近似、正向模式自动微分和反向模式自动…

ETCD高可用架构涉及常用功能整理

ETCD高可用架构涉及常用功能整理 1. etcd的高可用系统架构和相关组件1.1 Quorum机制1.2 Raft协议 2. etcd的核心参数2.1 常规配置2.2 特殊优化配置2.2.1 强行拉起新集群 --force-new-cluster2.2.2 兼容磁盘io性能差2.2.3 etcd存储quota 3. etcd常用命令3.1 常用基础命令3.1.1 列…

Java 数据结构篇-深入了解排序算法(动态图 + 实现七种基本排序算法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 实现冒泡排序 2.0 实现选择排序 2.1 选择排序的改良升级 3.0 实现堆排序 4.0 实现插入排序 5.0 实现希尔排序 6.0 实现归并排序 6.1 递归实现归并排序 6.2 使用…

HarmonyOS鸿蒙学习基础篇 - 通用事件

一、引言 HarmonyOS鸿蒙是华为推出的分布式操作系统&#xff0c;旨在为各种智能设备提供统一的操作系统。鸿蒙系统的一大特色是其强大的分布式能力&#xff0c;而通用事件则是实现这一能力的关键技术之一&#xff0c;本篇博客将介绍HarmonyOS鸿蒙中的通用事件。 二、 点击事件…