iOS开发多线程
这段时间一直在自学html,js,css。今天闲来无事,还是决定好好复习复习iOS的代码,前天swift之父Chris Lattner离开了苹果,群里热闹:“swift bug谁来修改?swift何去何从?” 好了扯远了,还是整理下多线程吧。
NSThread在实际开发中用到的很少了,(直说了除了[NSThread currentThread],我都不用),代码量以及需要手动去管理,并且线程管理相对不方便,所以对于NSThread不做介绍了,记住[NSThread currentThread]可以用来调试即可。
一、GCD需要掌握的
1、串行队列的创建
dispatch_queue_t q = dispatch_queue_create("com.example.gcd.mySerialDispatchQueue", NULL);
a、串行队列开启同步任务,在主线程顺序执行
dispatch_queue_t q = dispatch_queue_create("com.example.gcd.mySerialDispatchQueue", NULL);
for (int i = 0; i < 10; i ++) {
dispatch_sync(q, ^{
NSLog(@"___%@__%d",[NSThread currentThread],i);
});}
b、串行队列开启异步任务 开启2号(开启一个)线程 ,顺序执行
for (int i = 0; i < 10; i ++) {
dispatch_async(q, ^{
//串行队列 异步任务 开启2号(开启一个)线程 顺序执行
NSLog(@"%@__%d",[NSThread currentThread],i);
});}
c、串行队列中无论是同步任务还是异步任务,只要在这些任务中又开启了同步任务线程就会被锁死。
2、并行队列的创建
dispatch_queue_t q = dispatch_queue_create("com.tysx.189", DISPATCH_QUEUE_CONCURRENT);
与串行的区别DISPATCH_QUEUE_CONCURRENT与NULL的区别。
a、并行队列开启同步任务在主线程 顺序执行
dispatch_queue_t q = dispatch_queue_create("com.tysx.189", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i ++) {
dispatch_sync(q, ^{
NSLog(@"1%@___%d",[NSThread currentThread],i);
});}
b、并行队列开启异步任务会开多个线程 无序执行
for (int i = 0; i < 10; i ++) {
dispatch_async(q, ^{
NSLog(@"2%@___%d",[NSThread currentThread],i);
});}
c、并行队列的好处是可以随意嵌套而不会出现线程死锁情况,什么是线程死锁,我的理解是这样的,在主线程中,又开启了一个主线程的任务,那么由于该主线程永远都不会结束,所以开启的任务将永远都不会被执行到。
3、全局主队列只能开异步任务,同步任务会死锁,并且异步任务在主线程 顺序执行
for (int i = 0; i < 10; i ++) {
dispatch_async(dispatch_get_main_queue(), ^{
// 只能在主线程中执行的处理
NSLog(@"%@__%d",[NSThread currentThread],i);
});}
4、全局组队列的创建,类似于并行队列,同步任务主线程顺序执行,异步任务开多个线程无序执行。
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
5、这边只有十次循环都结束的时候 才会调用下面的nslog(done)
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10; i ++) {
dispatch_group_async(group, queue, ^{
NSLog(@"%d",i);
});}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"done");});
6、相当于线程依赖吧,前面2个执行完然后 执行barrier 然后再执行下面的内容
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-1");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-2");
});
7、相当于线程依赖吧,前面2个执行完然后 执行barrier 然后再执行下面的内容
dispatch_barrier_async(concurrentQueue, ^(){
NSLog(@"dispatch-barrier");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-3");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-4");
});
/**
* 下面方法 相当于一个for循环 只是在全部循环完成后才会执行done
*/
dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index){
NSLog(@"%zu",index);
});
NSLog(@"done");
二、NSOperationQueue
1、将nstimer 加入到runloop
+ (void)ADDTimer:(NSTimer *)timer{
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
2、常用会到主线程方法
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//这个可以成为回到主线程的方法。
// [self Printf];
}];
3、 开启子线程
[[[NSOperationQueue alloc]init] addOperationWithBlock:^{
//无序的开线程完成任务。
// [self Printf];
}];
4、这边如果设置 queue.maxConcurrentOperationCount = 1; 则相当于串行队列,如果不设置则相当于并行队列
NSOperationQueue * queue1 = [[NSOperationQueue alloc]init];
// queue.maxConcurrentOperationCount = 1;
for (int i = 0; i < 10; i ++) {
[queue1 addOperationWithBlock:^{
NSLog(@"%d",i);
// [self Printf];
}];
5、线程依赖的执行
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1");
}];
NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2");
}];
NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3");
}];
//adddependency 这里是建立依赖关系,就是说只有3执行完了 才执行2 然后执行1
[op1 addDependency:op2];
[op2 addDependency:op3];
[queue addOperation:op3];
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [queue addOperation:op3];
// });
// 会阻塞当前线程,等到某个operation执行完毕
// [op2 waitUntilFinished];
[queue addOperation:op2];
[queue addOperation:op1];
三、关于对同一个对象访问的处理
进入Xcode 8.0 以后 增加了新的调试功能。
进入eidt secheme 勾选thread sanitlzer 和pause on issues
这样在项目运行的时候,如果出现对于同一个对象进行的重复访问,则会提示出来。
这是时候可以考虑进行 加锁和互斥处理。详细信息可以去百度进行搜索,这边不做罗列。