多线程
ios多线程实现方案
ios多线程的应用
一个ios程序运行后,默认会开启1条线程,称为"主线程"或"UI线程".
主线程的主要作用
1.显示\刷新UI界面
2.处理UI事件(点击事件,滚动事件,拖拽事件等)
主线程的使用注意
不要将耗时的操作放到主线程中,耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种很卡的体验。
NSThread
1.Mac/ios 应用使用主线程来管理界面
2.主线程与后台线程之间的通信
performSelectorOnMainThread
performSelectorInBackground:withObject
3.锁
NSlock
@synchronized()////小括号里面放的是锁对象 self
{
}
4.常用函数
获取当前线程 [NSThread currentThread];
获取主线程 [NSThread mainThread];
线程的调度优先级
+/- (double)threadPriority;
+/- (BOOL)setThreadPriority:(double)p;
调度优先级的取值范围是0.0~1.0,默认0.5,值越大,优先级越高
线程的名字
-(void)setName:(NSString*)n;
-(NSString*)name;
GCD
GCD中有2个核心概念
任务:执行什么操作。
队列:用来存放任务。
同步、异步、并发、串行
同步:dispatch_sync() 在当前线程中执行任务,不具备开启新线程的能力
异步:
dispatch_async()在新的线程中执行任务,具备开启新线程的能力(
dispatch_get_main_queue()除外
)
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务。
内存管理
GCD的数据类型在ARC环境下不需要再做release
CF(Core Foundation)的数据类型在ARC\MRC环境下都需要再做release
1.何时使用:知道用户何时更新了系统,通常会用到block(脱字符号 ^ )
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{});
2.GCD支持名为代码队列的概念,使用时需要指定将代码放到哪个队列上。
- 默认队列
- 主队列–>类似于主线程
3.GCD函数在主线程上更新用户界面
dispatch_sync(dispatch_get_main_queue(),^{});
4.GCD是实现后台处理的首选方式,使用GCD进行异步处理时,要求block每次都按照它们在代码中出现的顺序执行
dispathch_queue_create(DISPATCH_QUEUE_SERIAL,0)
5.创建顺序队列
属性 dispathch_queue_t serialQueue;
6.”Dispatch Queue”执行处理的等待队列,按照追加的顺序(FIFO)执行处理。
两种Dispatch Queue
-
串行队列 Serial Dispatch Queue 等待现在执行中处理结束
Serial Dispatch Queue1–>使用一个线程
Serial Dispatch Queue2–>使用一个线程
Serial Dispatch Queue3–>使用一个线程
Serial Dispatch Queue4–>使用一个线程(多个 Serial Dispatch Queue可并行执行)
- 并发队列 Concurrent Dispatch Queue不等待现在执行中处理结束
dispatch_async(queue,blk0);
dispatch_async(queue,blk1);
dispatch_async(queue,blk2);
dispatch_async(queue,blk3);
dispatch_async(queue,blk4);
dispatch_async(queue,blk5);
dispatch_async(queue,blk6);
dispatch_async(queue,blk7);
7.如何得到 Dispatch Queue
- dispathch_queue_create(程序员管理内存)
- 获取系统标准提供的Dispatch Queue(系统管理内存)
1.main Dispatch Queue(Serial Dispatch Queue) //主队列
2.Global Dispatch Queue(Concurrent Dispatch Queue) //全局并发队列
8 Dispatch_set_target_queue
dispatch_queue_create函数生成的Dispatch Queue不管是Serial Dispatch Queue 还是Concurent Dispatch Queue,都使用与默认优先级Global Dispatch Queue相同执行优先级的线程。如果需要变更,就要用到dispatch_set_target_queue函数。
在后台执行动作处理的Serial Dispatch Queue的生成方法。
GCD相关函数
延时执行 void dispatch_after(dispatch_time_t when,dispatch_queue_t queue,dispatch_block_t block);
一次性代码
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"----once"); });
队列组
(保证执行完组里面的所有任务之后,再执行notify函数里面的block)
// 1.队列组 dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 2.下载图片1 __block UIImage *image1 = nil; dispatch_group_async(group, queue, ^{ NSURL *url1 = [NSURL URLWithString:@"http://1.jpg"]; NSData *data1 = [NSData dataWithContentsOfURL:url1]; image1 = [UIImage imageWithData:data1]; }); // 3.下载图片2 __block UIImage *image2 = nil; dispatch_group_async(group, queue, ^{ NSURL *url2 = [NSURL URLWithString:@"http://2.png"]; NSData *data2 = [NSData dataWithContentsOfURL:url2]; image2 = [UIImage imageWithData:data2]; }); // 4.合并图片 (保证执行完组里面的所有任务之后,再执行notify函数里面的block) dispatch_group_notify(group, queue, ^{ // 开启一个位图上下文 UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0); // 绘制第1张图片 CGFloat image1W = image1.size.width; CGFloat image1H = image1.size.height; [image1 drawInRect:CGRectMake(0, 0, image1W, image1H)]; // 绘制第2张图片 CGFloat image2W = image2.size.width * 0.5; CGFloat image2H = image2.size.height * 0.5; CGFloat image2Y = image1H - image2H; [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)]; // 得到上下文中的图片 UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext(); // 结束上下文 UIGraphicsEndImageContext(); // 5.回到主线程显示图片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = fullImage; }); });
版权声明:本文为博主原创文章,未经博主允许不得转载。