Swift多线程:使用GCD实现异步下载图片
GCD属于系统及的线程管理,功能很强大,比上两次咱们分享的Operation
要强大。有很多老前辈们已经创造了非常非常多的资料介绍GCD,因为大家都是把GCD放在了多线程内容分享的最开始,所以导致好多好多理论知识都被放在了GCD部分。
哈哈~幸好非典型技术宅英明神武的错峰出行,把一些基础概念放在了上两篇文章里面。极大的减轻了这篇文章的阅读负担。
既然前人都早了辣么多轮子,俺就不想再多介绍一些基础理论知识了。反正码再多的字,只会让大家立刻马上关掉这篇文章。而且上一篇关于Operation的阅读量就明显不高,看来大家不喜欢看啊。。。
那就容我偷偷懒嘛~重点还是分享一些代码吧。
不是说理论知识不重要啊,面试全都问这个。而且理论知识直接影响到对技术的理解深度,决定能在这条路上走多远。是会成为某个领域的大牛,还是只是简单的应用者。
1. GCD基础知识
纳尼?不是说不说基本概念了吗?easy~easy~easy~~~只介绍一些那些最最重要的,不了解就会影响到阅读这篇文章的内容啦。
其实GCD和Operation很多地方惊人的相似。废话,都是多线程,底层都差不多,能不相似嘛!
GCD使用只需要两步:
- STEP ONE:创建任务。
- STEP TWO:把任务放进队列里。
。。。。。。~!@#¥%……&*¥%#@!~@#¥%…… 把大象放进冰箱里需要几步?!两步!打开冰箱门,把大象放进去!宅胖,现在很想抽死你啊!
确实真的就是这样的。内心OS:这只是为了骗你入门,让你觉得好简单。
1.1 任务的分类
上面说了任务,任务只有两种方式:同步、异步。
- 异步(
asynchronous
)具备开启新线程的能力,也具备跳过当前代码继续往下执行的能力。 - 同步(
synchronous
)不具备开启新线程的能力,也不具备跳过当前代码继续往下执行的能力。
名称 | 开启新线程的能力 | 跳过当前代码继续往下执行的能力 |
---|---|---|
异步 | 有 | 有 |
同步 |
NULL
|
NULL
|
换句话简单的说,异步任务就是可以同时开启多个跑道,同时跑好多辆车。同步就是只有一条车道,堵死也飞不过去,只能乖乖的等着,一辆接一辆。
任务放入到队列里面,会遵循first in first out原则。举个恶心的例子,就像是拉屎,先吃先拉,后吃后拉。 哈哈~看了这个比方,别打死我~
1.2 队列的分类
队列呐,也只有两种:串行队列(Serial Dispatch Queue
)、并发队列(Concurrent Dispatch Queue
)。
串行队列(
Serial Dispatch Queue
): 让任务一个接着一个有序的执行,一个任务执行完毕后,再执行下一个任务。并发队列(
Concurrent Dispatch Queue
) 可以让多个任务同时执行,自动开启多个线程同时执行多个任务。
咦?有点晕,怎么感觉跟刚才的任务分类一样呐?没错!就是这样的。
下面为了让大家不要晕菜,我们把队列这个中文名字统一都叫做
Queue
,这样就和OperationQueue
对应起来了,就不会那么晕了。
Serial Queue
和Concurrent Queue
各自都有一个特殊的Queue
。
主队列(main queue
):是Serial Queue
中特殊的一种。只能在主线程中进行,并且主队列里面的任务,只有当主线程空闲的时候才能被执行。用来刷新UI使用。
全局队列(global queue
):是Concurrent Queue
中特殊的一种。用来执行耗时操作。
同时,GCD里面还可以自定义Queue。
1.3 排列组合开始
最开始的时候,咱们是不是说了,使用GCD就只有两步:创建任务,把任务放进Queue
里。
任务有两种:同步、异步。Queue
加上两种特殊的(不包括自定义的)一共有四种。来吧,开始排列组合吧。有八种吧。
名称 | 能够开启新线程 | 能够跳过当前代码继续进行 |
---|---|---|
异步 | 能 | 能 |
同步 | / | / |
Queue
|
串行队列Serial | 并行队列concurrent | 主队列main | 全局队列global |
---|---|---|---|---|
能够多个任务同时执行 | / | 能 | / | 能 |
哈哈哈O(∩_∩)O哈哈~????
彻底晕菜?
oooO ↘┏━┓ ↙ Oooo ( 踩)→┃你┃ ←(死 ) \ ( →┃√┃ ← ) / _)↗┗━┛ ↖(_/
来吧,直接告诉你结论吧。里面有几个特例。
☺ |
串行队列Serial Queue
|
并行队列concurrent Queue
|
主队列main Queue
|
全局队列global Queue
|
---|---|---|---|---|
异步 | 新线程、串行执行 | 新线程、并行执行 | 无新线程、串行执行 | 新线程、并行执行 |
同步 | 无新线程、串行执行 | 无新线程、串行执行 | 没事会锁死 | 无新线程、串行执行 |
看上面这个表,所以如果想要同时做事情,当然不能选同步任务啦。因为它完全没能力!搞不好还会造成锁死。
要想同时做事情,就选concurrent Queue
+ 异步,或者global Queue
+ 异步。 不过人家global Queue
本来就是concurrent Queue
特殊的一种。
如果有多任务,工作中最最省事儿常用的就是global Queue
+ 异步。单任务、刷新UI就用main Queue
+ 异步。
上面都没心思看也没关系。工作中,如果有多任务,首选
global Queue
+ 异步。单任务、刷新UI就用main Queue
+ 异步。
2. GCD的基础应用
我滴妈妈~经过上面的分析,最后,最基础的使用就两种了。 多任务:global Queue
+ 异步。 单任务、刷新UI就用main Queue
+ 异步。
说实话,我也是第一次这么大胆的简化。会不会被大神们拍死?坐等~~~~
2.1 global Queue
+ 异步任务
/// global Queue + 异步任务
@IBAction func globalAsyn(_ sender: Any) {//创建一个全局队列。//get a global queuelet globalQueue = DispatchQueue.global()for i in 0...10 {//使用全局队列,开启异步任务。//use the global queue , run in asynchronousglobalQueue.async {print("I am No.\(i), current thread name is:\(Thread.current)")}}
}
复制代码
我们看一下运行的结果,乱序打印的,并且没有在主线程中。这证明了确实是多个任务没有按照顺序执行。
2.2 main Queue
+ 异步任务
/// main Queue + 异步任务
@IBAction func mainAsyn(_ sender: Any) {//创建一个主队列//get a main queuelet mainQueue = DispatchQueue.mainfor i in 0...10 {//使用主队列,开启异步任务//use the main queue, run in asynchronousmainQueue.async {print("I am No.\(i), current thread name is:\(Thread.current)")}}
}
复制代码
我们看一下运行的结果,确实是顺序打印的。并且都执行在了主线程中。
2.3 小实践:实现异步下载图片
需求:异步下载一张图片,下载完成后显示在UI界面
实现后的效果图:
思路:
- 在当前UI动作之外,开启一个
global Queue
+异步,用来下载图片。因为过程可能很耗时。 - 等下载完成后,开启一个
main Queue
+异步,把下载的图片赋值,刷新UI。
这个小Demo其实也实现了线程间通讯。
@IBAction func asynDownloadImage(_ sender: Any) {let imageVC = ImageVC()DispatchQueue.global().async {if let url = URL.init(string: "https://placebeard.it/355/140") {do {let imageData = try Data(contentsOf: url)let image = UIImage(data: imageData)//因为宅胖家网络很好,为了模拟网络很耗时,就用了延时加载。DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(2), execute: {imageVC.imageView.image = imageimageVC.imageView .sizeToFit()})} catch {print(error)}}}navigationController?.pushViewController(imageVC, animated: true)}
复制代码
3. GCD的服务质量(优先级)
DispatchQoS.QoSClass
是在Swift中封装的关于描述服务质量的类。
这个在Operation
里面也见到过,级别越高,就会给分配的资源越多。但是并不是严格按照级别的高低来执行的。
这是一个枚举值:
public enum QoSClass {case background //后台默默执行,The background quality of service class.case utility //通用的,The utility quality of service class.case `default` //默认值,The default quality of service class.case userInitiated //用户发起的,The user-initiated quality of service class.case userInteractive //用来执行用户交互,The user-interactive quality of service class.case unspecified //没啥重要事情,The absence of a quality of service class.public init?(rawValue: qos_class_t)public var rawValue: qos_class_t { get }
}
复制代码
看到上面的枚举值,也大概能猜出来优先级的高低了。和界面相关的、用户的肯定是高的,后台默默执行的肯定是低的。
从高到低的顺序分别是:userInteractive
-> userInitiated
-> default
-> utility
-> background
-> unspecified
最基本的基础基本上就到这里了。掂量了一下,还有调度组、信号量、阻塞等等都还没写。这时候发现一篇写完GCD基础貌似不太现实,又不想一篇文章过长,那就拆开吧。下次再说。
最后,所有的代码都放在这里了:gitHub 下载后给颗Star吧~ 么么哒~(~o ̄3 ̄)~ 爱你们~
祝各位新春快乐~!~!
Swift多线程:使用GCD实现异步下载图片相关推荐
- Swift多线程:GCD进阶,单例、信号量、任务组
其实这个标题不知道怎么写了,都很碎,也没有想到特别合适的例子能够全部放在一起的.索性就这么平铺开吧. 1. dispatch_once,以及Swift下的单例 使用dispatch_once函数能保证 ...
- [翻译] LASIImageView - 显示进度指示并异步下载图片
LASIImageView – download image with progress indicator 翻译原网址:http://lukagabric.com/lasiimageview-d ...
- python 协程之异步下载图片
1.安装第三方模块 pip install aiofiles pip install aiohttp 2.示例 #! /usr/bin/env python3 import asyncio impor ...
- CGD 异步下载图片
CGD 异步下载图片 dispatch_queue_t squeue = dispatch_queue_create ( "abc" , NULL ); di ...
- python 异步下载图片_python3抓取异步百度瀑布流动态图片(二)get、json下载代码讲解...
制作解析网址的get 1 defgethtml(url,postdata):2 3 header = {'User-Agent':4 'Mozilla/5.0 (Windows NT 10.0; WO ...
- java异步下载图片_CMS项目实现异步图片下载
create table CMS_IMAGES ( id LONG PRIMARY KEY, --id wsrc varchar2(256),--远程图片地扯 lsrc varchar2(256),- ...
- python 异步下载图片_异步Python壁纸爬虫
My Blog:https://www.saky.site 欢迎来玩哈 打造一个壁纸爬虫来爬你的老婆/老公吧!!! 本次爬取的为 Alpha Coders壁纸站 ,壁纸充足质量高且画幅大,并且提供简 ...
- 如何异步下载图片显示进度条
本文案例中,使用原生协程结合requests库,而requests库本身不支持异步请求方式.但可以使用协程对象将requests库包装,运用协程executor对象使其requests库支持异步请求. ...
- Android多线程分析之一:使用Thread异步下载图像
打算整理一下对 Android Framework 中多线程相关知识的理解,主要集中在 Framework 层的 Thread, Handler, Looper, MessageQueue, Mess ...
最新文章
- Nginx配置文件粗解
- VS2012 ddk驱动编译与虚拟机联机调试设置(vs调试驱动)
- python3.8安装pip-CentOS7.2安装python3.8与pip
- 深蓝学院《从零开始手写VIO》作业六
- 基于VHDL的RISC microprocessor设计
- oracle19c连接MySQL_oracle19c的安装和使用navicat连接oracle数据库
- ZooKeeper系列(二)
- Guayadeque成为音乐爱好者的开源播放器的6个原因
- 深度学习——用向量重新组织输入数据
- 如何使用SubtitleWorkshop制作字幕
- 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)...
- stm32学习笔记:点阵模块74HC595、APM4953
- 【愚公系列】2022年04月 微信小程序-image图片
- android后台进程隐藏手段
- 深入java虚拟机视频教程_从原理到实战深入学习JAVA虚拟机,视频教程下载
- android sim卡应用程序,Android双SIM卡API
- MTK平台Metadata的加载(4)—Q版本后
- 变电站智能化改造升级 数字化运营的意义
- YGG SEA 投资 5 万美元,购买 ARPG 游戏《变形机甲》中的 NFT 资产
- 基于SpringBoot的漫画网站设计与实现
热门文章
- 郑哲:学习、应用初探与探索创新 | 提升之路系列(四)
- 从“幕后”走到“前台 ” 德力的C2M制造变革
- 计算机组成原理78h是什么,计算机组成原理
- 软件设计之耦合性与内聚性的区别
- mit6.824 2022 lab2
- 雅特力MCU--定时器级联学习
- “PDF修改器 2.5.2.0[强大的免费PDF文件编辑软件]”乃是假冒软件
- odbc spoon连接postgre_通过ODBC将Excel连接到PostgreSQL
- Python 实现VRay Bitmap的旋转和重复偏移
- python如何修改网页_python爬虫:使用BeautifulSoup修改网页内容