zoukankan      html  css  js  c++  java
  • 多线程

    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;
            });
        });

     

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

  • 相关阅读:
    转:pthread_detach()函数
    转: pthread_create()
    转:exit()与_exit()的区别
    转:perror和strerror的区别
    转:socket通信简介
    82-基于Xilinx Virtex-5LXT FPGA的四路光纤PCIE卡(4路光纤卡)
    18-基于双TMS320C6678 DSP的3U VPX的信号处理平台
    ZYNQ系列
    372-基于XC7VX690T的高速模拟信号、万兆光纤综合计算平台
    V7双雄-基于Virtex7XC7VX690T的高性能计算板卡解决方案
  • 原文地址:https://www.cnblogs.com/H7N9/p/4888842.html
Copyright © 2011-2022 走看看