多线程:Operation(一)
1. 进程和线程
1.1 进程
- 进程:正在运行的应用程序叫进程
- 进程之间都是独立的,运行在专用且受保护的内存空间中
- 两个进程之间无法通讯
通俗的理解,手机上同时开启了两个App。这两个App肯定是在不同的进程中的。所以这两个App之间是独立的,内存中的数据不能互相窜来窜去,两个App之间也没有办法进行通讯。
两个App之间没有办法进行通讯?我说的是正常情况下。当然还是有不正常情况啊,例如使用iOS提供的极少数的几种进程间通讯的工具。
1.2 线程
- 线程:进程想要执行任务,必须要有线程,每个进程至少有一条线程。
- 线程就是用来干活的。
- 程序一启动,就会启动进程。进程默认开启一条线程。
干活的线程?对啊,活太多,或者不想彼此互相等着浪费时间,当然可以找几个人同时干了。
例如在项目上,产品经理需求都没有完全写完,也不妨碍先设计一个大概的数据框架啊。例如需求没有完全定下来,不妨碍UI童鞋提前设计啊,大不了再改嘛~ HOHO~怎么听上去都像是黑话。
1.3 多线程
单核CPU同一时间,CPU只能处理1个线程,只有1个线程在执行任务。
多线程的同时执行 : 其实是CPU在多条线程之间快速切换(调度任务)。
如果CPU调度线程的速度足够快,就造成了多线程同时执行的假象
如果线程非常多,CPU会在多条线程之间不断的调度任务,结果就是消耗了大量的CPU资源,效率下降:
- 每个线程调度的频率会降低
- 线程的执行效率会下降
iPhone手机是几核的?
A7 : iPhone 5S , 双核
A8: iPhone 6、iPhone 6 Plus,双核
A9:iPhone 6S、iPhone 6S Plus,双核
A10:iPhone 7、iPhone 7 Plus,2+2核
1.4 iOS中的多线程
刚才说了,iOS App一旦运行,默认就会开启一条线程。这条线程,我们通常称作为“主线程”
主线程的作用:
- 刷新UI
- 处理UI事件,例如点击、滚动、拖拽。
如果主线程的操作太多、太耗时,就会造成App卡顿现象严重。所以,通常我们都会把耗时的操作放在子线程中进行,获取到结果之后,回到主线程去刷新UI。
2. Operation
我们来看看基础使用:
// 最基本的使用Operation
private func basicOperation() {
// 第一步:创建Operation
let op = Operation.init()
// 第二步:把要执行的代码放入operation中
op.completionBlock = { print(#function,#line,Thread.current)
}
// 第三步:创建OperationQueue
let opQueue = OperationQueue.init()
// 第四步:把Operation加入到线程中
opQueue.addOperation(op)
}
使用BlockOperation创建operatoin,并直接运行。咱们看看会在哪条线程执行。
//创建一个简单的BlockOperation
private func CreatBasicBlockOperation() {
//使用BlockOperation创建operation
let operation = BlockOperation.init {
//打印,看看在哪个线程中 print(#function,#line,Thread.current)
} //直接运行operation,看看运行在哪个线程中
operation.start()
}
打印一下看看运行的结果:
这就是我们说,创建完Operation如果直接运行,就会在当前线程执行。也就是说,如果实在主线程创建并且start的,那就会在主线程执行;如果是在子线程创建并且start的,那就会在子线程执行。
3. Basic Demo
在这个例子里面,需求如下:
1,在子线程加载每个图片的数据
2,图片数据下载完毕之后,显示出来
3,开始请求数据的时候,让指示符开始转动
4,所有图片下载完毕后,指示符停止转动
3. Basic Demo
在这个例子里面,需求如下:
1,在子线程加载每个图片的数据
2,图片数据下载完毕之后,显示出来
3,开始请求数据的时候,让指示符开始转动
4,所有图片下载完毕后,指示符停止转动
3.2 Swift中的do catch
这个是Swift和OC不一样的地方。Swift中出现了可选值这么一个东西,这个不是这次的重点。想深入了解的童鞋可以参看这篇:?和 !的使用
Swift 里有四种方法来处理错误:
- 把错误从函数传递到调用函数的代码里
- 使用一个 do-catch 语句来处理错误
- 把错误当做一个可选值来处理
- 断言这个错误不会发生
因为Demo里面用到了do catch,那咱们就只说do catch.
在Swift的标准try中,是要配合do catch的。
下面是do-catch语句的一般格式,如果do分句内的代码抛出了一个错误,它就被catch分句捕获,并判断由哪个分句来处理此错误。
do {
try expression
statements
} catch pattern {
statements
} catch pattern where condition {
statements
}
3.3 优先级
在思维导图里面出现了两个优先级。一个是属于Operation 的,一个是属于OperationQueue的。那咱们分看看看这两个都是啥。
3.3.1 Operation中的优先级
Operation里面的这个叫做qualityOfService
public enum QualityOfService : Int {
case userInteractive
case userInitiated
case utility
case background
case `default`
}
userInteractive:最高优先级,用于用户交互事件
userInitiated :次高优先级,用于用户需要马上执行的事件
utility:普通优先级,用于普通任务
background:最低优先级,用于不重要的任务
default:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级
3.3.2 operationQueue 里面的优先级
operationQueue中表示优先级的属性是queuePriority
,表示操作在队列中的优先级。
public enum QueuePriority : Int {
case veryLow
case low
case normal
case high
case veryHigh
}
这些优先级都是相对的,并不是是说必须要执行完最高的才执行次重要的。这里面并没有一个特别严格顺序。只是在分配资源上有倾向性。如果队列需要有严格的执行顺序,还是要添加依赖关系的,这个是我们下一篇文章要分享的内容。
4. 案例实现
Operation 基本应用及优先级小案例。
实现后效果如下:
这个Demo里面,用了两种方法创建Operation。
在startBasicDemo
,使用的是闭包创建Operation的方式。在startPriorityDemo
里面使用的是自定义的构造方法创建的Operation,然后把任务数组加入到线程中。
代码:
// Operation 案例
fileprivate func startBasicDemo()
{
let operationQueue = OperationQueue.init()
operationQueue.maxConcurrentOperationCount = let activityIndicator = UIActivityIndicatorView()
activityIndicator.startAnimating() let a = UIImageView(frame: CGRect(x: , y: , width: , height: ))
self.view.addSubview(a)
let b = UIImageView(frame: CGRect(x: , y: , width: , height: ))
self.view.addSubview(b)
let c = UIImageView(frame: CGRect(x: , y: , width: , height: ))
self.view.addSubview(c)
let d = UIImageView(frame: CGRect(x: , y: , width: , height: ))
self.view.addSubview(d) let imageViews = [a, b, c, d]
for imageView in imageViews {
if let url = URL(string: "https://placebeard.it/355/140")
{
do {
let image = UIImage(data:try Data(contentsOf: url)) DispatchQueue.main.async
{
imageView.image = image
}
}catch
{
print(error)
}
}
}
// global queue
DispatchQueue.global().async
{
[weak self] in
// 等待所有操作都完成了,回到主线程停止刷新器。
// wait Until All Operations are finished, then stop animation of activity indicator
operationQueue.waitUntilAllOperationsAreFinished()
DispatchQueue.main.async
{
activityIndicator.stopAnimating()
} }
}
设置了优先级的Demo:
fileprivate func startPriorityDemo() {
operationQueue.maxConcurrentOperationCount =
activityIndicator.startAnimating() var operations = [Operation]()
for (index, imageView) in (imageViews?.enumerated())! {
if let url = URL(string: "https://placebeard.it/355/140") {
// 使用构造方法创建operation
let operation = convenienceOperation(setImageView: imageView, withURL: url) //根据索引设置优先级
switch index {
case :
operation.queuePriority = .veryHigh
case :
operation.queuePriority = .high
case :
operation.queuePriority = .normal
case :
operation.queuePriority = .low
default:
operation.queuePriority = .veryLow
} operations.append(operation)
}
} // 把任务数组加入到线程中
DispatchQueue.global().async {
[weak self] in
self?.operationQueue.addOperations(operations, waitUntilFinished: true)
DispatchQueue.main.async {
self?.activityIndicator.stopAnimating()
}
} }
多线程:Operation(一)的更多相关文章
- iOS多线程自定义operation加载图片 不重复下载图片
摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用: 2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验 2:自定义operati ...
- operation 多线程
2.Cocoa Operation 优点:不需要关心线程管理,数据同步的事情.Cocoa Operation 相关的类是 NSOperation ,NSOperationQueue.NSOperati ...
- 多线程:Operation(二)
1. Operation 设置依赖关系 先看看如何设置operation的依赖关系. 啥叫依赖关系?有啥用啊?打个比方咱们要做一个听音乐的付费App项目,需要经过登陆.付费.下载.播放四个步骤.其实一 ...
- Operation System - Peterson's Solution算法 解决多线程冲突
Person's solution 是用来一种基于软件的解决关键区域问题的算法(critical-section). 它并不是完美的,有可能不对地工作.并且是限制解决两个进程同步的问题. 可是它非常e ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程池篇1
在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...
- C#多线程之线程同步篇2
在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...
- 多线程爬坑之路-Thread和Runable源码解析
多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
随机推荐
- mybatis传入某一列的值,然后设置这一列的值是这个
select '${action}' as action from table name parameterType="map"可以指定为map,然后这边就可以用${xxx}来取值 ...
- 第 7 章 Data 类型
目录 第 7 章 Data 类型 一.创建方式 二.转时间戳 其他 第 7 章 Data 类型 @(es5) 参考了: 阮一峰javascript的标准.<javascript高级教程> ...
- win7远程ubuntu桌面以及Ubuntu14.04安装搜狗输入法 Ubuntu远程登录windows系统
windows远程登录ubuntu有命令行以及桌面两种方式. 1.命令行的方式我认为putty这款软件比较好,这之前需要在ubuntu电脑上安装上ssh,命令如下(安装与启动): sudo apt-g ...
- 所使用的“System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35”版本高于所引用的程序集“System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”的版本
System.Web.Mvc.dll引用是感叹号. 解决方法:新建mv3应用程序,右键选择System.Web.Mvc.dll 查看所引用的路径. 在旧程序中重新引用即可.C:\Program Fil ...
- Centos安装elasticsearch教程
elasticsearch安装是ytkah在做laravel电商站内搜索要实现的,通过自己的搜索和学习能力不算很费力解决了.下面就整理一下安装elasticsearch教程,服务器是Centos 7, ...
- Mysql事件监控日志
建立监控表: CREATE TABLE `t_event_history` ( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, `dbname ...
- 数据库---mysql的介绍和安装
MySQL数据库 一.简介: mysql是数据库管理软件:套接字:服务端,客户端 支持并发:操作得是共享得数据 处理锁,数据安全,性能 用别人得软件,得照着别人得规范,组织自己得语法规则 二.概述: ...
- bootbox.js官方文档中文版
bootbox.js官方文档中文版简介:Bootbox.js是一个小型的JavaScript库,基于Bootstrap模态框开发,用于创建可编程的对话框. 不像原生的alert等对话框,所有的Boot ...
- dll相关总结
1.动态链接库的使用有两种方式,一种是显式调用.一种是隐式调用. (1) 显式调用:使用LoadLibrary载入动态链接库.使用GetProcAddress获取某函数地址. (2) 隐式调用:可以使 ...
- GENIL_BOL_BROWSER 中显示的Object Name 是root object的名字
EMPLOYEE 是root object 的名字. 2: dynamic query parameters 对应于:srch_attr. Each BOL object appears in a t ...