07 |「异步任务」

本文介绍了软件与操作系统的关系,详细阐述了进程和线程的概念,以及如何通过异步任务和AsyncTask实现并发任务加载。重点讲解了并发问题的解决策略,如资源冲突和使用回调机制来保证UI的响应性。

前言

实践是最好的学习方式,技术也如此。

一、软件与操作系统

  • 软件

    • 定义: 软件是程序的载体,写的代码,打包出来就是软件,就能安装在各种设备上,然后运行在操作系统上。(程序就是用于指导计算机的一系列抽象指令,而软件是程序实际编译运行在计算机上而存在的产品。软件是程序的一种载体和实现形式。两者关系就像设计和产品、理论和实践)
    • 分类:系统软件(操作系统),应用软件(都要运行在操作系统上);
  • 操作系统

    • 作用
      • 1)负责跟系统硬件打交道,把用户的各种操作(比如鼠标点击、键盘输入等)翻译给计算机硬件,然后将结果告诉用户;
      • 2)管理其他软件;
    • 管理其他软件
      • 操作系统如何管理其它软件:通过管理进程;

二、进程与线程

  • 软件是程序的载体,每个程序都是一个进程;

  • 每个程序都有一个进程,线程是进程的一部分,线程是操作系统能调度的最小单元;

  • 通俗例子解释

    • 背景:村庄
      • 村长:操作系统; 管理每个家庭;单独指挥一个人去做事(一个线程);
      • 一个软件就是一个家庭,这个家庭就是一个进程;
      • 一个家庭是一个进程,家中有我、父亲、母亲(每个人都是一个线程);
  • 线程的优点

    • 使用线程可以提高程序的运行速度,节省时间和成本;
    • 变串行为并行,提高速度,节省时间;
      • 串行:一件事同一时刻只有一个人做;
      • 并行:一件事同一时刻有多个人做;
  • 多线程资源冲突:多个线程在同一时刻操作同一个资源;

    • 操作资源:对资源进行了修改;
      	// 定义资源i
      	int i = 10;
      	// 访问资源,没有修改i
      	println(i);
      	// 操作资源,对i进行了修改
      	i = 1;
      
  • 线程是进程的一部分,是操作系统调度的最小单位(是调度的最小单位,不是持有资源的最小单位);

  • 资源都是在进程中的,进程是持有资源的最小单位;线程可以使用资源,但是不能持有资源;

  • 每一个进程都有一块内存,这个内存是所有线程共享的。每一个线程都有一个缓存,这个缓存是自己独占的;

  • 例如,进程 p,进程 p 有个线程 a,线程 a 的执行逻辑

    • CPU 将 a 需要的数据从进程 P 的内存读入线程 a 的缓存;如 i;
    • a 对自己缓存的数据进行操作;如 i ++;
    • a 执行完毕,cpu 将 a 缓存的数据 i 写回到进程 p 的内存中;
  • 资源冲突:多个线程在同一时刻操作同一个资源;同一时刻,同一目标;
    线程 a 执行的同时,进程 p 中 的另一个线程 b 也在执行,且也用到了 P 内存中的 i;那么,线程 b 执行完成后,i 是多少呢,是以线程 a 执行的为准,还是线程 b 执行的为准;

  • 解决资源冲突:不同时或不同目标(破坏同一时间或同一目标这两个条件)

    • 不同时:排队,变并行为串行;在 i 被读入线程 a 的内存中时,加个标记;其它线程来看到这个标记会等着,等到线程 a 执行完成将 i 写回到内存中时,再把标记清除我,并通知其他线程,其他线程再开始执行。

1、进程

  • 进程(Process)是操作系统分配资源的基本单位,它是一个执行中的程序实例;
  • 每个进程都有自己独立的内存空间,不同进程的内存是相互独立的;
  • 在Android系统中,每个应用都会以一个新的进程运行,系统会自动帮我们管理这些进程;
  • 默认情况下,Android系统会为每个App分配一个进程。这个默认进程里可以包含多个Activity);
  • 当在这个进程内启动一个新的Activity时,是直接在该进程create一个Activity实例,不会创建新进程;
  • 多个Activity会共享该应用进程的资源和内存空间;
  • 单纯启动新Activity并不会造成进程切换,对系统资源影响较小

2、线程

* 线程就是让==一个程序==有能力==同时完成多件事情==;
  • 线程是正在运行的程序中的一条独立的执行路径;
  • 主线程
    • 当 Android 程序启动时,系统会创建一个主线程,也称为 UI 线程;
    • UI 线程是应用程序与 Android UI 工具包中的组件交互的方式(在这个线程中可以更新UI,处理用户输入事件等。UI组件像Activity、View都是在UI线程中初始化和创建的。);
    • UI线程负责处理用户界面的创建、更新和响应用户交互事件,确保应用的用户界面保持流畅、响应迅速,并提供良好的用户体验
    • UI 线程只能处理和界面相关的工作,比如绘制界面,处理点击事件等,区分UI线程和工作线程,就是让耗时操作不阻塞界面,以保证应用的流畅性和用户体验;
  • 后台(工作)线程是除主线程或 UI 线程之外的任何线程;
  • AsyncTask:
    • 来简化这种需要后台工作的场景;
    • 可以把AsyncTask看成一个工人,我们在主线程中告诉它需要做什么工作,它会自己另开一个线程(后台线程)去工作。工作完成后它再回到主线程,通过回调方法将结果返回给我们。这样下来,我们的主线程(UI线程)就可以专注于更新界面,不会被阻塞。而AsyncTask也封装了线程管理和线程间通信的复杂性,我们只需要告诉它做什么工作就可以了;
    • AsyncTask 通过异步线程可以避免阻塞,回调机制又可以获取结果;

三、实现

  • 回调:至于回调的概念,它表示一种函数或方法,当特定事件发生时就会被执行。回调不会主动调用,而是在满足条件时由别处调用以完成响应。在Android中,回调机制很常见,例如点击事件的onClick()就是一个回调方法。

AsyncTask通过线程间的回调,很好地结合了后台工作与UI更新,极大地方便了程序逻辑的管理。

  • TextView、Button;
  • 用户单击 Button 时,应用程序会休眠一段随机时间,然后在唤醒时在 TextView 中显示一条消息;
// 第一个泛型参数String: 表示异步任务输入参数的类型:String
// 第二个泛型参数Integer: 表示后台任务执行进度的类型:Integer
// 第三个泛型参数Bitmap: 表示异步任务最终返回结果的类型:

// 知识点:<T>表示类型参数T,用于在定义Box类时传入实际的类型
public class MyAsyncTask 
   extends AsyncTask <String, Integer, Bitmap>{}

应用现在有一个在后台执行工作的 AsyncTask 类,现在可以为“启动任务”按钮实现 onClick 方法来触发后台任务;

doInBackground():实现代码以执行要在单独线程上执行的工作

onPostExecute():在doInBackground()执行结束后,自动在UI线程被调用,并接收doInBackground()的返回值。函数参数就是从doInBackground()中返回的结果

四、异步任务加载器

EditText,Button,TextView
需求:用户在 EditText 中输入书名并点击按钮,查询用户正在查找的图书的作者和书名,结果显示在 TextView 中

五、解决并发

  • 并发
    • 定义:指同一个时间段,程序中有多个代码片段同时运行或交替运行的情况;
  • 解决并发的基本操作
    • 核心:破坏同一时刻或同一目标;
    • 破坏同一时间的核心:排队;
    • 加锁:在变量 a 被一个线程读取后,就加一个锁,如果被写回来,就释放锁,其他线程过来后发现有锁,就等着;实现同时只有一个线程使用变量 a
    • 类比酒店入住,客人得到钥匙,并且锁门,这样别人就进不去了;离开再交还钥匙,下一个人就能入住了;即排队;
    • 加了锁之后,原来的并行(多个线程一起执行),变成了串行(线程排队执行)
下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学和电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优先或最小成本优先的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row 和 col 分别指示方格所在的行和列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row 和 offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个写代码的修车工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值