博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS:多线程技术GCD的使用
阅读量:6249 次
发布时间:2019-06-22

本文共 6184 字,大约阅读时间需要 20 分钟。

GCD的使用:

1.队列的类型
     1.1 主队列:mian queue,主线程队列,负责更行UI的操作。是一个串行的队列。
     1.2 系统默认的并行队列:global queue,按优先级分类。
     1.3 自定义的队列:可以创建串行队列或者是并行的队列
 
2.任务
     2.1 封装的形式:block方法或C语言的函数
     2.2 添加到队列的方式:同步或异步(只对并行队列有区别)
         例如服务器请求:
         同步:提交请求->等待服务器处理(这个期间客户端浏览器不能干任何事)->处理完毕返回   
         异步:请求通过事件触发->服务器处理(这个期间客户端浏览器仍可以干其他的事)->处理完毕返回
 
3.特殊使用
     3.1 只执行一次 dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);(多用于单例模式)
     3.2 延时执行    dispatch_after(dispatch_time_t when,dispatch_queue_t  queue,dispatch_block_t block);
     3.3 成组的执行任务       dispatch_group_create(void);
     3.4 创建自定义的队列    dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
     3.5 创建默认的全局队列 dispatch_get_global_queue(long identifier, unsigned long flags)
     3.6 获取主队列             dispatch_get_main_queue(void)
     3.7 异步执行                
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
     3.8 同步执行              dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
     3.9 多次执行  dispatch_apply(size_t iterations, dispatch_queue_t queue,void (^block)(size_t));
     …………………等等…………………
 

4.几个方法参数解释:

<1>创建自定义的队列    dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

const char *label:队列名字                   dispatch_queue_attr_t attr:队列执行方式(串行、并行)

<2>创建默认的全局队列 dispatch_get_global_queue(long identifier, unsigned long flags)

long identifier:队列执行的优先级           unsigned long flags:默认为0即可

<3>多次执行         dispatch_apply(size_t iterations, dispatch_queue_t queue,void (^block)(size_t));

size_t iterations:执行次数      dispatch_queue_t queue:队列      void (^block)(size_t):block函数块

 
5.队列方式宏定义(用于创建自定义队列时的参数)

#define DISPATCH_QUEUE_SERIAL NULL         //串行

#define DISPATCH_QUEUE_CONCURRENT        //并行

 

6.队列优先级宏定义(创建全局队列时的参数)

#define DISPATCH_QUEUE_PRIORITY_HIGH 2

#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0

#define DISPATCH_QUEUE_PRIORITY_LOW (-2)

#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN

 

7.更能区分

主队列:专门用来执行主线程的,进行UI的更新操作

全局队列或自定义队列:用来添加并执行其他的线程,进行数据的操作

 

 具体举例如下:

例子1:采用不分组的方式,将多线程添加到队列中,然后进行多线程的操作。

1.准备UI界面布局:拖入一个文本视图控件,并关联相关的类中,同时在类中声明一个票数变量

@interface ViewController (){    NSInteger _tickets;}@property (weak, nonatomic) IBOutlet UITextView *textView;@end

2.设置票数,同时将原来文本视图中默认的数据清空,取消自动布局便于后面添加数据时自动滚动文本视图

//设置数据和文本视图 _tickets = 20; [self.textView setText:@""]; self.textView.layoutManager.allowsNonContiguousLayout = NO;

3.创建全局队列,并设置优先级,设置并行方式

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4.用GCD创建任务线程,并将线程添加到队列中,采用异步执行方式

dispatch_async(queue, ^{        [self GCDSellTicketMethod:@"GCD售票线程-1"];    });    dispatch_async(queue, ^{        [self GCDSellTicketMethod:@"GCD售票线程-2"];    });

5.定义更新UI的方法

#pragma mark -更新UI的操作

-(void)appendTextView:(NSString *)text{    //1.获取原来的数据    NSMutableString *content = [NSMutableString stringWithString:self.textView.text];    NSRange range = NSMakeRange(content.length, 2);    //2.追加新的内容    [content appendString:[NSString stringWithFormat:@"\n%@",text]];    [self.textView setText:content];        //3.滚动视图    [self.textView scrollRangeToVisible:range];}

6.定义任务线程的执行方法

#pragma mark -执行线程的操作

-(void)GCDSellTicketMethod:(NSString *)name{    while (YES)    {        if(_tickets > 0)        {            //使用GCD            dispatch_async(dispatch_get_main_queue(), ^{                //更新UI                NSString *info = [NSString stringWithFormat:@"总票数:%ld,当前的线程:%@",_tickets,name];                [self appendTextView:info];                                //卖票                _tickets--;            });                        //线程休眠            if([name isEqualToString:@"GCD售票线程-1"])            {                [NSThread sleepForTimeInterval:0.3f];            }            else            {                [NSThread sleepForTimeInterval:0.2f];            }        }        else        {            //使用GCD更新UI            dispatch_async(dispatch_get_main_queue(), ^{                NSString *info = [NSString stringWithFormat:@"票已经卖完,当前线程:%@",name];                [self appendTextView:info];            });                        //退出线程            break;        }    }}

 

例子2:采用分组的方式,将线程组添加到队列中,然后进行多线程的操作。

1.准备UI界面布局:拖入一个文本视图控件,并关联相关的类中,同时在类中声明一个票数变量

@interface ViewController (){    NSInteger _tickets;}@property (weak, nonatomic) IBOutlet UITextView *textView;@end

2.设置票数,同时将原来文本视图中默认的数据清空,取消自动布局便于后面添加数据时自动滚动文本视图

//设置数据和文本视图 _tickets = 20; [self.textView setText:@""]; self.textView.layoutManager.allowsNonContiguousLayout = NO;

3.创建一个线程分组

dispatch_group_t group = dispatch_group_create();

4.创建自定义的队列,并设置队列执行方式为并行方式

  dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);

5.用GCD创建任务线程组,并将线程组添加到队列中,采用分组异步执行方式

  dispatch_group_async(group,queue, ^{

      [self GCDSellTicketMethod:@"GCD售票线程-1"];

  });   

  dispatch_group_async(group,queue, ^{

      [self GCDSellTicketMethod:@"GCD售票线程-2"];

  });

6.等线程组中的所有任务完成后,会接收到通知,更新UI

dispatch_group_notify(group, queue, ^{        dispatch_async(dispatch_get_main_queue(), ^{            NSString *info = [NSString stringWithFormat:@"票已经卖完"];            [self appendTextView:info];        });    });

7.定义更新UI的方法

#pragma mark -更新UI的操作

-(void)appendTextView:(NSString *)text{    //1.获取原来的数据    NSMutableString *content = [NSMutableString stringWithString:self.textView.text];    NSRange range = NSMakeRange(content.length, 2);    //2.追加新的内容    [content appendString:[NSString stringWithFormat:@"\n%@",text]];    [self.textView setText:content];        //3.滚动视图    [self.textView scrollRangeToVisible:range];}

8.定义任务线程的执行方法

#pragma mark -执行线程的操作

-(void)GCDSellTicketMethod:(NSString *)name{    while (YES)    {        if(_tickets > 0)        {            //使用GCD            dispatch_async(dispatch_get_main_queue(), ^{                //更新UI                NSString *info = [NSString stringWithFormat:@"总票数:%ld,当前的线程:%@",_tickets,name];                [self appendTextView:info];                                //卖票                _tickets--;            });                        //线程休眠            if([name isEqualToString:@"GCD售票线程-1"])            {                [NSThread sleepForTimeInterval:0.3f];            }            else            {                [NSThread sleepForTimeInterval:0.2f];            }        }        else        {               //退出线程            break;        }    }}

 

两种情况的演示结果如下:

 

 

 

 

 

 

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
分类: 
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4859089.html,如需转载请自行联系原作者
你可能感兴趣的文章
设计模式之-代理模式
查看>>
Fragment
查看>>
一个五年架构师凭什么基本年薪酬就可以达到50万
查看>>
npm进阶
查看>>
[译] 僵尸币时代即将到来?
查看>>
Java设计模式之单例模式(几种写法及比较)
查看>>
总结:44个Python3字符串内置方法大全及示例
查看>>
2018年最值得关注的30个Vue开源项目
查看>>
docker之DockerSwarm的了解
查看>>
大区块的BCH给智能合约更大的发展潜力
查看>>
springcloud(五):熔断监控Hystrix Dashboard
查看>>
七年软件测试历程,回过头来,最能帮助我的还是这些.....
查看>>
yum 安装nginx
查看>>
前端(js+JQuery非空校验)
查看>>
[Android] ImageView.ScaleType设置图解
查看>>
银行卡卡号验证
查看>>
VS的内存断点
查看>>
Jenkins实战演练之Linux系统节点管理
查看>>
为什么init脚本需要lock文件
查看>>
利用python的zmail模块发送邮件
查看>>