首页 > 系统 > iOS > 正文

iOS NSThreadGCD 线程与队列(二)

2019-11-06 09:42:57
字体:
来源:转载
供稿:网友
////  GCD_ViewController.m//  ZM_NSThreadGCD////  Created by ZM on 2015/2/9.//  Copyright © 2015年ZM. All rights reserved.//#import"GCD_ViewController.h"#import "BaseHeader.h"@interfaceGCD_ViewController ()@end@implementationGCD_ViewController- (void)viewDidLoad {    [superviewDidLoad];    self.title= @"GCD_VC";       NSString *title=@"";    CGFloat width = 120;    for (inti=1; i<11; i++) {               title = [NSStringstringWithFormat:@"case%d",i];        [selfaddBtnTitle:titleframe:CGRectMake(10,50+ (35+10)*i, width, 35)Tag:i];    }       CGFloat yy = SSHEIGHT-90;    [selfaddBtnTitle:@"attentionCase3_1"frame:CGRectMake(10, yy, width, 35)Tag:111];    [selfaddBtnTitle:@"attentionCase3_2"frame:CGRectMake(10*2+width, yy, width, 35)Tag:222];    [selfaddBtnTitle:@"solveCase3_1"frame:CGRectMake(10, yy+45, width,35)Tag:333];         }- (void)myBtnClick:(UIButton*)Btn{       if (Btn.tag==1) {       [selfcase1];    }elseif (Btn.tag==2) { [selfcase2];    }elseif (Btn.tag==3) { [selfcase3];    }elseif (Btn.tag==4) { [selfcase4];    }elseif (Btn.tag==5) { [selfcase5];    }elseif (Btn.tag==6) { [selfcase6];    }elseif (Btn.tag==7) { [selfcase7];    }elseif (Btn.tag==8) { [selfcase8];    }elseif (Btn.tag==9) { [selfcase9];    }       if (Btn.tag==111) {       [selfattentionCase3_1];    }elseif (Btn.tag==222) { [selfattentionCase3_2];    }elseif (Btn.tag==333) { [selfsolveCase3_1];    }}/** *  以下4个GCD方法的区别: dispatch_async          异步任务 dispatch_sync           同步任务 dispatch_barrier_async  为异步执行调度队列:提交一个路障 dispatch_barrier_sync   为同步执行调度队列:提交一个路障  dispatch_get_main_queue    主队列 dispatch_queue_t           并行队列 dispatch_get_global_queue  全局并行队列  *///例一:dispatch_sync同步任务 提交Block在主线程 中执行- (void)case1 {       dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT);    dispatch_sync(queue1, ^{        NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main}           });}//例二:dispatch_async异步任务 提交Block在分线程 中执行- (void)case2 {       dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue1, ^{        NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 3, name = (null)}           });}//例三:我们分别用sync和async向主队列提交Block,结果Block都是在主线程中执行:- (void)case3 {       //我们用sync如下的方式去提交Block:    dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue1, ^{        dispatch_sync(dispatch_get_main_queue(), ^{            NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main}        });    });   }//注意3_1:在主线程不能用sync(同步)提交Block执行任务,否则会引起死锁:- (void)attentionCase3_1 {          dispatch_sync(dispatch_get_main_queue(), ^{        NSLog(@"任务一");    });    NSLog(@"任务二");    //因为往queue中提交Block,总是追加在队列尾部的,而queue执行Block的顺序为先进先出(FIFO),所以任务一需要在当前队列它之前的任务(任务二)全部执行完,才能轮到它。    //任务一等待任务二完成,任务二等待任务一完成,相互等待_被阻塞,程序被死锁在这了}//注意3_2:在主线程能用async(异步)提交Block执行任务- (void)attentionCase3_2 {       dispatch_async(dispatch_get_main_queue(), ^{        NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main}    });}//解决3_1 问题- (void)solveCase3_1 {       // 全局并行队列    // 这应该是唯一一个并行队列, 只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。    // 因为全局队列和主队列是两个队列,所以任务一的执行,并不需要等待任务二。    dispatch_sync(dispatch_get_global_queue(0,0), ^{        NSLog(@"任务一");    });    NSLog(@"任务二");}//例四:建立栅栏_执行任务dispatch_barrier_async- (void)case4 {    dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue, ^{        NSLog(@"任务1");    });    dispatch_async(queue, ^{        NSLog(@"任务2");    });    dispatch_async(queue, ^{        NSLog(@"任务3");    });       //建立栅栏_执行任务dispatch_barrier_async    dispatch_barrier_async(queue, ^{        NSLogline(@"/n  %@/n  %@/n  %@",                  @"任务1,2,3的顺序不一定",                  @"任务4_在中间",                  @"最后是5、6、7、8、9任务顺序不一定");    });       dispatch_async(queue, ^{        NSLog(@"任务5");    });    dispatch_async(queue, ^{        NSLog(@"任务6");    });    dispatch_async(queue, ^{        NSLog(@"任务7");    });    dispatch_async(queue, ^{        NSLog(@"任务8");    });    dispatch_async(queue, ^{        NSLog(@"任务9");    });    //结论:dispatch_barrier_async 它的作用可以用一个词概括--承上启下,它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。当然它的作用导致它只有在并行队列中有意义。       //注意:当然这里有一点需要注意的是:dispatch_barrier_(a)sync只在自己创建的并发队列上有效,在全局(Global)并发队列、串行队列上,效果跟dispatch_(a)sync效果一样。       //3)dispatch_barrier_sync这个方法和dispatch_barrier_async作用几乎一样,都可以在并行queue中当做栅栏。    //唯一的区别就是:dispatch_barrier_sync有GCD的sync共有特性,会阻塞提交Block的当前线程,而dispatch_barrier_async是异步提交,不会阻塞。}//例五:例如我们在一个读写操作中,我们就可以如下使用:- (void)case5 {       //一个读写操作中:我们要知道一个数据,读与读之间是可以用线程并行的,但是写与写、写与读之间,就必须串行同步或者使用线程锁来保证线程安全。但是我们有了dispatch_barrier_async       dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue, ^{        NSLog(@"读操作_1");    });    dispatch_async(queue, ^{        NSLog(@"读操作_2");    });    dispatch_barrier_async(queue, ^{        NSLog(@"写操作_1");    });    dispatch_barrier_async(queue, ^{        NSLog(@"写操作_2");    });    dispatch_async(queue, ^{        NSLog(@"读操作");    });    //结论:这样写操作的时候,始终只有它这一条线程在进行。而读操作一直是并行的。这么做充分利用了多线程的优势,还不需要加锁,减少了相当一部分的性能开销。实现了读写操作的线程安全。    //读与读:线程并行    //写与写、写与读:必须串行同步或者使用线程锁}//例六:4)dispatch_sync,我们来讲讲它和dispatch_barrier_sync的区别。二者因为是sync提交,所以都是阻塞当前提交Block线程。       //而它俩唯一的区别是:dispatch_sync并不能阻塞并行队列。其实之前死锁有提及过,担心大家感觉疑惑,还是写个例子:- (void)case6 {    dispatch_queue_t queue = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT);    // dispatch_sync    dispatch_sync(queue, ^{        dispatch_async(queue, ^{            NSLog(@"任务二");        });        dispatch_async(queue, ^{            NSLog(@"任务三");        });        //睡眠2秒//        [NSThread sleepForTimeInterval:2];        NSLog(@"任务一/n ");    });    //输出结果:任务三 任务二 任务一 (二、三顺序不固定,一最后,很显然,并行队列没有被sync所阻塞。)}//例七:而dispatch_barrier_sync 可以阻塞并行队列(栅栏作用的体现):- (void)case7 {    dispatch_queue_t queue = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT);    // dispatch_barrier_sync    dispatch_barrier_sync(queue, ^{        dispatch_async(queue, ^{            NSLog(@"任务二");        });        dispatch_async(queue, ^{            NSLog(@"任务三");        });        //睡眠2秒//        [NSThread sleepForTimeInterval:2];        NSLog(@"任务一");    });    //输出结果:任务一 任务二 任务三 (一首先,二、三顺序不固定)}/**  同:dispatch_sync、dispatch_barrier_sync 都能阻塞 主队列  区别:dispatch_sync不能阻塞并行队列       dispatch_barrier_sync 可以阻塞并行队列 */- (void)case8 {   }- (void)case9 {   }@end
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表