多线程

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)的数据类型在ARCMRC环境下都需要再做release

1.何时使用:知道用户何时更新了系统,通常会用到block(脱字符号 ^ )

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{});

2.GCD支持名为代码队列的概念,使用时需要指定将代码放到哪个队列上。

  1. 默认队列
  2. 主队列–>类似于主线程

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

  1. 串行队列 Serial Dispatch Queue 等待现在执行中处理结束
    多个Serial Dispatch Queue
    Serial Dispatch Queue1–>使用一个线程
    Serial Dispatch Queue2–>使用一个线程
    Serial Dispatch Queue3–>使用一个线程
    Serial Dispatch Queue4–>使用一个线程

    (多个 Serial Dispatch Queue可并行执行)

  2. 并发队列 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);

Concurrent Dispatch Queue执行顺序

7.如何得到 Dispatch Queue

  1. dispathch_queue_create(程序员管理内存)
    这里写图片描述
    这里写图片描述
    这里写图片描述
  2. 获取系统标准提供的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;
        });
    });

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/H7N9/p/4888842.html