介绍:
网络请求、图片下载、文件处理、数据存储、任务执行
串行: 任务一个任务一个的进行,时间之和, 队列相关
并行: 任务同时进行,
同步:线程阻塞,任务执行完成之后才会执行下一个
异步:不知道什么时候返回,不会阻塞其他任务
1 进程 线程
线程是任务执行的基本单元. 进程中所有任务通过线程来完成
单核 时间片轮转,分配时间片交替执行,宏观上并发执行
多核
2 技术方案
PThread 基于C++,用的少
NSThread
GCD
NSOperation NSOperationQueue
-1, PThread基于C++语言开发使用的,
-2, NSThread,基于OC开发,苹果封装好的,面向对象的实现的. 3种方式创建
初始化: 通过[alloc]initwithTarget开辟子线程 start方法
通过detachNewThreadSelector toTarget 方式创建并执行线程, 静态方法,类方法
通过performSelectInBackground 方式创建线程
[self performSelect:onThread:]
[self performSelectInBackground : WithObject:] 子线程 sleep(1)
[self performSelectOnMainThread: WithObject:] 主线程
属性方法:
name,
setThreadPriority 优先级 0 - 1 之间
线程锁 买票系统模拟 3种方式
关键词: synchronized
[NSCondition lock]
NSLock
3 GCD 自动管理线程生命周期 线程池,OC语法,block,方便灵活,
-1,
global_queue: 全局并发 参数: long型 , 可以设置优先级low high default
main_queue 主线程 UI线程
dispatch_async(dispatch_get_ global_queue(0,0),^{
[NSThread sleepForTimeInverval:3]
get_main_queue 刷新UI
})
-2,
串行queue, 保证线程顺序执行, 一个线程中串行执行
dispatch_queue_create : 参数1: 名字, 参数2: NULL(SERIAL)和CONCURRENT, 串行和并行队列
CONCURRENT 是多个线程并发
-3 dispatch_group_ 多个任务异步处理,回调通知,处理其他业务, 异步请求的统一回调
创建queue, CONCURRENT并行,
创建dispatch_group
情况一: 线程内部 正常同步执行
dispatch_group_async(group, queue)^{
request1
[NSThread sleepForTimeInverval:3]
}
dispatch_group_async(group, queue)^{
request2
[NSThread sleepForTimeInverval:3]
}
dispatch_group_async(group, queue)^{
request3
[NSThread sleepForTimeInverval:3]
}
拿到所有task结束之后的回调, 回来是在异步线程
dispatch_group_notify(group,queue, ^{
"All tasks over"
})
情况二: 线程内部,又开辟异步线程,比如网络请求
就用以下解决
dispatch_group_enter(group);
dispatch_group_leave(group); 异步回来之后, 释放掉 request被group持有
-4 信号量 dispatch_semaphore_signal
使用场景
主要是控制线程并发数
阻塞请求
第一个函数是创建一个信号量。每一个信号量都有一个计数,该函数唯一的参数就是该信号量的初始计数值。
第二个函数每调用一次,信号量的计数会增加1。在调用该函数之前信号量的计数小于0,那么该函数会唤醒一个等待第三个函数返回的线程。
第三个函数每调用一次,信号量的计数会减小1.在调用该函数之后,如果信号量的计数值不小于0,那么该函数会立即返回;如果小于0,会等待,直到被第二个函数发出信号。如果有多个函数在等待信号,那么按照先后顺序依次获得信号。
// dispatch_semaphore_signal有两类用法:a、解决同步问题;b、解决有限资源访问(资源为1,即互斥)问题。
// dispatch_semaphore_wait,若semaphore计数为0则等待,大于0则使其减1。
// dispatch_semaphore_signal使semaphore计数加1。
// a、同步问题:输出肯定为1、2、3。
5. 倒计时
//NSEC_PER_SEC是秒,*1是每秒
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), NSEC_PER_SEC * 1, 0);
//设置响应dispatch源事件的block,在dispatch源指定的队列上运行
dispatch_source_set_event_handler(timerQueue, ^{
其他:
-1 单例:dispatch_once_t, 整个生命周期只执行一次
-2 延迟执行: dispatch_after(DISPATCH_TIME_NOW,(int64_tF)(2*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
}); 避开一个方法. 缺点: 不能cancel, 页面已经释放掉, 容易崩溃. 可以设置一个变量. yes no不执行
dispatch_suspend(queue); //暂停队列queue
dispatch_resume(queue); //恢复队列queue
barri 多组任务
倒计时
1.关于GCD倒计时,实际开发中遇到的问题在于线程使用,要知道倒计时每次改变都是在主线程对按钮的UI进行重新绘制,所以必须保证倒计时按钮变化的通知,其他操作要在其他线程,否则,页面卡死,卡顿将会出现
2.一般用到倒计时,大多是在收取验证码,当收到验证码,填写完毕的时候,点击进行其他操作,必须杀死/停止当前线程,否则只能等到倒计时为0方可进行,道理就是如1所描述
4 NSOperation NSOperationQueue NSBlockOperation
创建使用 main方法
最大并发数 线程池 setMaxConcurrentOperationCount:
依赖:[OperA addDependency: OperB] 先执行B.
如果是异步执行,需要runLoop去控制执行. 当前任务操作完之后, 再执行其他线程
NSRunloop 循环监听状况,线程不会自动结束, 除非手动要求结束
参考:
网友评论