一、重要概念
1. 线程是进程的一个实体。进程在执行时拥有独立内存单元,而线程之间可以共享内存,能够拥有更好的性能和用户体验。
ps.多线程要适度使用,并不是线程越多,性能越好
2. 一个线程,多个任务,一个任务执行完后才进行下一个任务,称为串行。多个线程,分担多个任务,并发执行任务,称为并行。
3. 同步sync,阻塞式,一个任务未完成会影响其他的进程。
异步async,非阻塞式,一个线程的任务未完成不会对其他线程的任务造成阻塞和影响。
ps.异步和并发 概念不同。
4. 临界资源:并发环境中有着固定数量被多个线程竞争的资源。
5. 互斥: 对资源的访问是排他式的。
6. 死锁: 两个或多个线程都等待对方结束。
7. 活锁: 想要执行的线程总是发现其他的线程正在执行以至于长时间或永远无法执行。
二、线程的创建
直接创建线程的两种方式:
1. `NSThread detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument;`
2. `NSThread *thread = [[NSThread alloc] initWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument];`
`[thread start];`
- ps. 这种方式可以设置(配置)线程 属性。
配置线程:
01.设置优先级: threadPriority
02.绑定数据: threadDictionary
03.设置名称: name属性
04.启动线程: start
05.退出线程: exit
三、线程同步方式
1.NSLock (上锁)
2.NSConditon
3.@synchronized代码块
四、线程安全
1. 所有属性声明都尽量使用nonatomic.
2. 尽量避免多个线程竞争同一资源的情况。
3. 让服务器端处理复杂逻辑,客户端只获取结果。
五、NSOperation
1.使用NSOperation的子类NSInvocationOperation和NSBlockOperation
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(foo:) object:nil];
[operation start];//同步方式执行
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{\\}];
[operation2 start];//同步方式执行
//异步方式执行
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
ps.如果需要控制队列中线程数量,可以使用下列形式
[queue setMaxConcurrentOperationCount:5];
--
六、GCD入门
1. GCD简介
让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
2. GCD底层维持一个FIFO队列,该队列称为dispatch queue,它可以保证先进来的任务先得到执行。dispatch queue分为三类:
2.1 private serial dispatch queue: 用户队列。该任务队列默认的是串行执行,可以通过dispatch_queue_create()函数来创建该队列,可以通过第二个参数来指定串行还是并行。
2.2 global dispatch queue: 全局队列,有三个队列,优先级不同。可以通过dispatch_get_global_queue()函数来获得,需要传人优先级。
2.3 main dispatch queue: 提交该队列的任务在主线程上执行。可以通过dispatch_get_main_queue()函数来获得此队列。
常用的:
第一个:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAU LT, 0), ^{
// 耗时的操作 dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面 });
});
第二个:(在指定的时间之后执行)
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
dispatch_after(time, queue, ^{});
第三个:(多个任务完成后刷新主界面事例)
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{});
dispatch_group_async(group, queue, ^{});
dispatch_group_async(group, queue, ^{});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{});
dispatch_release(group);
第四个:(同时进行读写操作的示例)
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_barrier_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
第五个:(挂起和恢复派发队列)
dispatch_suspend(queue); //挂起
dispatch_resume(queue); //恢复
第六个:(只执行一次处理)
static dispatch_once_t token;
dispatch_once(&token, ^{});