• ios线程总结(持续更新ing)


    一、什么是线程:

    1、1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)

    2、线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行

    3、1个线程中任务的执行是串行的,如果要在1各线程中执行多个任务,那么只能一个一个地按顺序执行这些任务,也就是说,在同一时间内,1个线程只能执行1个任务

    二、什么是多线程

    1、1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务  

    例:进程 ——>车间  ,线程——>车间工人

    2、多线程的原理:同时间,CPU只能处理1条线程,只有1条线程在工作(执行),多线程并发(同时)执行,其实质是CPU快速地在多条线程之间调度(切换),当CPU调度线程的速度足够块,就造成了多线程并发执行的假象

    三、什么是主线程

    1、一个iOS程序运行后,默认会开启1条线程,成为“主线程”或“UI线程”

    2、主线程的主要作用:显示,刷新UI界面 ;处理UI事件(比如点击事件、滚动事件、拖拽事件等)

    3、使用主线程需要注意:别将比较耗时的操作放到主线程,会卡UI(阻塞UI)

    四、iOS中多线程的实现方案

    1、pthread

        简介:一套通用的线程API,适用于UnixLinuxWindows等系统;跨平台,可移植;使用难度大。

        语言:C

        线程生命周期:程序员管理

        使用频率:几乎不用

    示例代码: 

    2、NSThread

         简介:使用更加面向对象,简单易用,可直接操作线程对象

         语言:OC

         线程生命周期:程序员管理

         使用频率:偶尔使用

    创建线程实例代码:

    创建方式一:

    创建方式二:

    创建方式三(隐式创建并启动):

    线程安全:

               1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,很容易引发数据错乱和数据安全问题。

    线程安全代码实例(加互斥锁):

    互斥锁使用格式: @synchronized(self){ //需要锁定的代码}

    注意:锁定1份代码只能用1把锁,用多把锁是无效的,且加过多的锁会消耗大量的CPU资源降低程序效率

    线程间通讯:

    线程其他方法:

    3、GCD

         简介:旨在替代NSThread等线程技术,充分利用设备的多核

         简介:C

         线程生命周期:自动管理

         使用频率:经常使用

        3.1 什么是GCD:全称(Grand Central Dispatch,可译为"伟大的调度中心")

        3.2 GCD的优势:

               3.2.1 GCD是苹果公司为多核并行运算提出的解决方案;

               3.2.2 GCD会自动利用更多的CPU内核(比如双核,四核)

               3.2.3 GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

        3.3 GCD中有2个核心概念

               3.3.1 任务:执行什么操作

               3.3.2 队列:用来存放任务

              

        3.4 GCD的使用就2个步骤:

               步骤一:定制任务(确定想做的事情)

               步骤二:将任务添加到队列中(CGD会自动将队列中的任务取出,放到对应的线程中执行),任务的取出遵循队列的FIFO原则,先进先出,后进后出

        3.5 GCD中有2个用来执行任务的函数

              3.5.1 用同步的方式执行任务(在当前线程执行,不开启新线程)

              dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

              queue:队列

              block:任务

              3.5.2 用异步的方式执行任务(会开启新线程)

              dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

             在这里需要注意一点:GCD的队列可分为2大类型

                   (1)并发队列(Concurrent Dispatch Queue),可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只能在异步(dispatch_async)函数下才有效.

                     (2) 串行队列(Serial Dispatch Queue),让任务一个接着一个执行(一个任务执行完毕后,再执行下一个任务).

    注意:同步和异步主要影响能不能开启新的线程,同步在当前线程中执行,不具备开启新线程的能力;异步在新的线程中执行任务,具备开启新线程的能力。并发和串行主要影响任务的执行方式,并发是多个任务并发(同时)执行,串行是一个任务执行完毕后再执行下一个任务。

        3.6 队列类型:(全局并发队列,串行队列,主队列)

              全局并发队列:GCD默认已经提供了全局的并发队列,提供整个应用使用,不需要手动创建

                                  获取全局并发队列的函数:dispatch_get_global_queue

                                  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

                                  参数1:全局并发队列的优先级(影响该队列的调度次数)

                                             DISPATCH_QUEUE_PRIORITY_HIGH 2  高

                                             DISPATCH_QUEUE_PRIORITY_DEFAULT 0  默认
                                             DISPATCH_QUEUE_PRIORITY_LOW (-2)  低
                                             DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  后台

                                  参数2:该参数暂时没有任何作用,传0

             串行队列:GCD中获得串行队列有2种途径

                           途径1:使用dispatch_queue_create函数创建串行队列
                                     dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

                                      参数1:队列名称;参数2:队列属性,一般用NULL即可

                                      注:非ARC,需要释放创建的队列  dispatch_release(queue);

                            途径2:使用主队列(跟主线程相关的队列),主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行。获取主队:dispatch_get_main_queue()

        3.7 GCD同步异步以及队列的组合方式:主要掌握以下第一种方式即可,其他的组合方式可以直接忽略

    /**  组合类型一:
     *  async -- 并发队列(最常用)
     *  会不会创建线程:会,一般同时开多条
     *  任务的执行方式:并发执行
     */

    - (void)asyncGlobalQueue
    {
        // 获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        // 将 任务 添加 全局队列 中去 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
         dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });

    }

    /** 组合类型二:
     *  async -- 串行队列(有时候用)
     *  会不会创建线程:会,一般只开1条线程
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     */
    - (void)asyncSerialQueue
    {
        // 1.创建一个串行队列,手动的,队列名称为heyifu.queue
        dispatch_queue_t queue = dispatch_queue_create("heyifu.queue", NULL);
        
        // 2.将任务添加到串行队列中 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });

        
        // 3.非ARC,需要释放创建的队列
    //    dispatch_release(queue);
    }

    /**组合类型三:不会用到,这种方式组合是多余的,这样的效果与直接把任务放到主线程中调用是一样的
     *  sync -- 并发队列
     *  会不会创建线程:不会
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     *  并发队列失去了并发的功能
     */
    - (void)syncGlobalQueue
    {
        // 获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        // 将 任务 添加到 全局并发队列 中 同步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });


    }

    /**组合类型四:不会用到,这种方式组合是多余的,这样的效果与直接把任务放到主线程中调用是一样的
     *  sync -- 串行队列
     *  会不会创建线程:不会
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     */
    - (void)syncSerialQueue
    {
        // 创建一个串行队列
        dispatch_queue_t queue = dispatch_queue_create("heyifu.queue", NULL);
        
        // 将 任务 添加到 串行队列 中 同步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });

    }

    /**组合类型五:
     *  async -- 主队列(很常用)不会开启新线程,一般用在线程间的通讯
     */
    - (void)asyncMainQueue
    {
        // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        // 2.添加 任务 到主队列中 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });

        dispatch_async(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });

    }

    /**
     *  sync -- 主队列(不能用---会卡死)
     */
    - (void)syncMainQueue
    {
        NSLog(@"syncMainQueue----begin--");
        
        // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        // 2.添加 任务 到主队列中 异步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });

        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });

        
        NSLog(@"syncMainQueue----end--");
    }

    总结:

        全局并发队列 手动创建串行队列 主队列
    同步(sync)  

    1.没有开启新线程

    2.串行执行任务

    1.没有开启新线程

    2.串行执行任务

    1.没有开启新线程

    2.串行执行任务

    异步(async)  

    1.有开启新线程

    2.并发执行任务

    1.有开启新线程(只开1条)

    2.串行执行任务

    1.没有开启新线程

    2.串行执行任务

    注意:使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列

        3.8 GCD 线程间的通讯(子线程执行完耗时操作,回到主线程)

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        dispatch_async(queue, ^{
            NSLog(@"donwload---%@", [NSThread currentThread]);
            // 1.子线程下载图片
            NSURL *url = [NSURL URLWithString:@"http://img2.bdstatic.com/static/searchdetail/img/dragtip1_f3e8b97.png"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [UIImage imageWithData:data];
            
            // 2.回到主线程设置图片
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"setting---%@ %@", [NSThread currentThread], image);
                [self.button setImage:image forState:UIControlStateNormal];
            });
        });
    }

    4、NSOperation

        简介:基于CGD(底层是GCD),比GCD多了一些简单实用的功能,使用更加面向对象

        语言:OC

        线程生命周期:自动管理

        使用频率:经常使用

  • 相关阅读:
    Leetcode Spiral Matrix
    Leetcode Sqrt(x)
    Leetcode Pow(x,n)
    Leetcode Rotate Image
    Leetcode Multiply Strings
    Leetcode Length of Last Word
    Topcoder SRM 626 DIV2 SumOfPower
    Topcoder SRM 626 DIV2 FixedDiceGameDiv2
    Leetcode Largest Rectangle in Histogram
    Leetcode Set Matrix Zeroes
  • 原文地址:https://www.cnblogs.com/HOYF/p/5074571.html
Copyright © 2020-2023  润新知