iOS多线程拾贝------操作巨人编程

iOS多线程拾贝------操作巨人编程

多线程

基本

  • 实现方案:pthread - NSThread - GCD - NSOperation

    • Pthread

      • 多平台,可移植
      • c语言,要程序员管理生命周期
      • 创建
      //这里已经开启了多线程,直接在这里调用子线程想要调用的代码
      void * run(void *pramga) {
      NSLog(@"-------");
      return NULL;
      }
      
      - (IBAction)btnClick:(id)sender {
      pthread_t pthread;
      pthread_create(&pthread, NULL, run, NULL);
      }
    • NSThread
      • 面向对象,简单实用
      • 创建
      //隐式创建并启动线程
      [NSThread detachNewThreadSelector:@selector(threadRun:) toTarget:self withObject:@"etund"];
      或者
      //创建线程并且启动线程
      [self performSelectorInBackground:@selector(threadRun:) withObject:@"etund"];
      或者
      //上述两个优点是可以快速的创建并启动线程,方便快捷,但是不能对线程进行多余属性的设置,而下面一种方法就可以对线程实例属性的设置,但是要记得要手动开启线程。
      NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun:) object:@"etund"];
      [thread start];

GCD

  • 听说全称是叫“牛逼的中枢调度器”,但是我还是喜欢叫大中央调度
  • 纯C语言,有很多强大的函数
  • 优势:(纯属板书)
    • GCD是苹果公司为多核的并行运算提出的解决方案
    • GCD会自动利用更多的CPU内核(比如双核、四核)
    • GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    • 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
  • 核心:清楚什么是任务,队列
    • 串行与并行不能决定是否要开启新县城
    • 并行表明具有创建新线程的能力,但不一定创建新线程
  • 常用GCD内容
    • 串行同步(并行同步/全局队列同步),由于串行同步,并行同步,以及全局队列同步都是不创建线程按顺序执行,所以归为一类来讲。(不开任何子线程,在主线程中执行)

      //串行
      dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_SERIAL);
      //并行
      //dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);
      dispatch_sync(queue, ^{
      
        NSLog(@"%@---1",[NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
        NSLog(@"%@----2",[NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
        NSLog(@"%@----3",[NSThread currentThread]);
      });
      运行结果
      2015-07-08 19:09:39.611 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}---1
      2015-07-08 19:09:39.612 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}----2
      2015-07-08 19:09:39.612 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}----3
    • 串行异步 (开启一个子线程,在子线程中执行)
      dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_SERIAL);
      dispatch_async(queue, ^{
        NSLog(@"%@---1",[NSThread currentThread]);
      });
      dispatch_async(queue, ^{
        NSLog(@"%@---2",[NSThread currentThread]);
      });
      dispatch_async(queue, ^{
        NSLog(@"%@---3",[NSThread currentThread]);
      });
      
      /*运行结果
      2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---1
      2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---2
      2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---3
      */
    • 并行异步(全局队列异步)虽然线程的执行顺序不一样,但是任务从队列里面拿出来放进线程的顺序是按照先进先出的这是根本,基础。(有几个任务,开启几个子线程,在各自的子线程中执行)
      dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);
      dispatch_async(queue, ^{
        NSLog(@"%@---1",[NSThread currentThread]);
      });
      dispatch_async(queue, ^{
        NSLog(@"%@---2",[NSThread currentThread]);
      });
      dispatch_async(queue, ^{
        NSLog(@"%@---3",[NSThread currentThread]);
      });
      //   虽然线程的执行顺序不一样,但是任务从队列里面拿出来放进线程的顺序是按照先进先出
      /*
      *2015-07-08 19:27:46.060 Pthread-多平台[68694:318231] <NSThread: 0x7f9a89c126b0>{number = 4, name = (null)}---2
      2015-07-08 19:27:46.060 Pthread-多平台[68694:318230] <NSThread: 0x7f9a8c211400>{number = 5, name = (null)}---3
      2015-07-08 19:27:46.060 Pthread-多平台[68694:318171] <NSThread: 0x7f9a89f9efe0>{number = 3, name = (null)}---1
      */
    • 主队列异步,不开任何子线程,在主线程中运行,也对应了那句话,异步队列只是具有开启子线程的能力,但是不一定开子线程。
      //    主队列异步(不开线程)
      dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@---1",[NSThread currentThread]);
      });
      dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@---2",[NSThread currentThread]);
      });
      dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@---3",[NSThread currentThread]); ;
      });
      /*
      2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---1
      2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---2
      2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---3
      */
    • 主队列同步
      - (void)gcdTest_2_4{
        NSLog(@"=-=-=-");
        //    主队列同步(阻塞)
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"%@---1",[NSThread currentThread]);
        });
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"%@---2",[NSThread currentThread]);
        });
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"%@---3",[NSThread currentThread]);
        });
        NSLog(@"=-=-=-");
      }

      ------------至此,基本GCD队列已经被差不多就这样了,下面来一下有趣的用法

    • GCD队列组,有这么一个需求,你的一个步骤要在其他步骤完成之后才能完成,也就是后续步骤要依赖于前期步骤,这是GCD队列组以及Barrier队列(栅栏队列)不失为一个好办法,
//GCD队列组方式
        //    (线程组)(线程通讯)
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    //    加载图片1
    dispatch_group_async(group, queue, ^{
        NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c2e882eb8b0df41bd5ac6e39e8.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        self.image1 = [UIImage imageWithData:data];
    });
    //    加载图片2
    dispatch_group_async(group, queue, ^{
        NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/ac6eddc451da81cbd668501c5666d01608243151.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        self.image2 = [UIImage imageWithData:data];
    });

    //    合并
    dispatch_group_notify(group, queue, ^{
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
        [self.image1 drawAsPatternInRect:CGRectMake(0, 0, 50, 100)];
        [self.image2 drawAsPatternInRect:CGRectMake(50, 0, 50, 100)];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        //GCD线程之间的通信
        dispatch_async(dispatch_get_main_queue(), ^{
            self.myView.image = image;
        });
        });

//栅栏dispatch_barrier方式
        dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);//创建多个线程
    dispatch_async(queue, ^{
        NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c2e882eb8b0df41bd5ac6e39e8.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        self.image1 = [UIImage imageWithData:data];
    });
    dispatch_async(queue, ^{
        NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/ac6eddc451da81cbd668501c5666d01608243151.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        self.image2 = [UIImage imageWithData:data];
    });

    dispatch_barrier_async(queue, ^{

    });

    dispatch_async(queue, ^{
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
        [self.image1 drawAsPatternInRect:CGRectMake(0, 0, 50, 100)];
        [self.image2 drawAsPatternInRect:CGRectMake(50, 0, 50, 100)];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        dispatch_async(dispatch_get_main_queue(), ^{
            self.myView.image = image;
        });
    });
  • 延迟加载

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      // 2秒后异步执行这里的代码...
    });
  • 快速迭代,当我们不需要注重迭代的顺序,只需要快速获得子元素的时候,GCD的快速迭代为你提供了途径
      //    (快速迭代)
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_apply(self.view.subviews.count, queue, ^(size_t index) {
          id obj = self.view.subviews[index];
          NSLog(@"---%zu---%@",index,obj);
      });
      /*
      2015-07-08 22:26:39.851 Pthread-多平台[972:17366] ---0---<_UILayoutGuide: 0x7fd86b644e00; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7fd86b643ab0>>
      2015-07-08 22:26:39.851 Pthread-多平台[972:17444] ---2---<UIImageView: 0x7fd86b645ba0; frame = (100 100; 100 100); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x7fd86b643290>>
      2015-07-08 22:26:39.851 Pthread-多平台[972:17435] ---1---<_UILayoutGuide: 0x7fd86b6457b0; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x7fd86b644040>>
       */
  • once一次性代码(单例模式设计),有时候我们需要用到单例模式做一些操作例如:传值时,就会用到单例设计模式,设计单例模式的方法很多,其中最重要的是要做到线程安全,而GCD就提供了这么一个结构体来保证在创建单例过程中的线程安全
ETPerson.h
+ (instancetype)sharePerson;
ETPerson.m
@implementation ETPerson
static ETPerson *_person;

+ (instancetype)sharePerson{
    static dispatch_once_t onceDispatch;
    dispatch_once(&onceDispatch, ^{
        _person = [[ETPerson alloc] init];
    });
    return _person;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceDispatch;
    dispatch_once(&onceDispatch, ^{
        _person = [super allocWithZone:zone];
    });
    return _person;
}

- (id)copyWithZone:(NSZone *)zone{
    return _person;
}
@end
调用
//    onece(单例)
    NSLog(@"%@----%@------%@-------%@------%@-----%@",[[ETPerson alloc] init],[[ETPerson alloc] init],[ETPerson copy],[ETPerson copy],[ETPerson sharePerson],[ETPerson sharePerson]);
    /*运行结果
     2015-07-08 23:26:57.292 Pthread-多平台[1350:37528] <ETPerson: 0x7fc4bb4041c0>----<ETPerson: 0x7fc4bb4041c0>------ETPerson-------ETPerson------<ETPerson: 0x7fc4bb4041c0>-----<ETPerson: 0x7fc4bb4041c0>
     */

线程通信

  • 线程之间的通信,线程的通信,在一个进程中,线程往往不是鼓励存在的,多个线程之间需要经常进行通信
  • 线程间通信的体现
    • 在一个线程传递数据给另外一个线程
    • 在一个线程中执行完成任务后,转到另一个线程继续执行任务
  • NSThread的线程通信

    //这个方法是指在当前线程运行完后调到主线程里面运行
      - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
    //这个方法是指在当前线程运行完后调用另外一个线程里面运行
      - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait
  • GCD的线程通信,GCD的线程通信十分简单,只是在代码块里面调用代码块,直接上代码吧。
从子线程回到主线程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行耗时的异步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程,执行UI刷新操作
        });
});
至此,iOS里面简单的多线程GCD以及NSThread以及PThread部分就入门了,明天更新NSOPeration。
时间: 2024-08-07 08:26:16

iOS多线程拾贝------操作巨人编程的相关文章

iOS多线程编程

1. 进程,线程, 任务 进程:一个程序在运行时,系统会为其分配一个进程,用以管理他的一些资源. 线程:进程内所包含的一个或多个执行单元称为线程,线程一般情况下不持有资源,但可以使用其所在进程的资源. 任务:进程或线程中要做的事情. 在引入线程的操作系统中,通常把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位. 线程比进程更小,对其调度的开销小,能够提高系统内多个任务的并发执行程度. 一个程序至少有一个进程,一个进程至少有一个线程.一个程序就是一个进程,而一个程序中的多个任

线程同步-iOS多线程编程指南(四)-08-多线程

首页 编程指南 Grand Central Dispatch 基本概念 多核心的性能 Dispatch Sources 完结 外传:dispatch_once(上) Block非官方编程指南 基础 内存管理 揭开神秘面纱(上) 揭开神秘面纱(下) iOS多线程编程指南 关于多线程编程 线程管理 Run Loop 线程同步 附录 Core Animation编程指南 Core Animation简介 基本概念 渲染架构 几何变换 查看目录 中文手册/API ASIHTTPRequest Openg

iOS多线程编程(四)------ GCD(Grand Central Dispatch)

一.简介 是基于C语言开发的一套多线程开发机制,也是目前苹果官方推荐的多线程开发方法,用起来也最简单,只是它基于C语言开发,并不像NSOperation是面向对象的开发,而是完全面向过程的.如果使用GCD,完全由系统管理线程,我们不需要编写线程代码.只需定义想要执行的任务,然后添加到适当的调度队列(dispatch_queue).GCD会负责创建线程和调度你的任务,系统会直接提供线程管理. 二.任务和队列 GCD中有两个核心概念 (1)任务:执行什么操作 (2)队列:用来存放任务 GCD的使用就

iOS多线程编程Part 1/3 - NSThread &amp; Run Loop

iOS多线程编程Part 1/3 - NSThread & Run Loop 02 JUNE 2013 前言 多线程的价值无需赘述,对于App性能和用户体验都有着至关重要的意义,在iOS开发中,Apple提供了不同的技术支持多线程编程,除了跨平台的pthread之外,还提供了NSThread.NSOperationQueue.GCD等多线程技术,从本篇Blog开始介绍这几种多线程技术的细节. 对于pthread这种跨平台的多线程技术,这本Programming with POSIX Thread

IOS多线程操作

多线程的概念 进程 ·正在运行中的程序被成为进程,负责程序运行的内存分配 ·没一个进程都有自己独立的虚拟内存空间 线程 ·线程是进程中一个独立的执行路径也称之为控制单元 ·一个进程至少包含一条线程,主线程 ·可以将耗时的执行路径如网络请求放在其他线程中执行 创建线程的目的就是为了开启一条新的执行路径,运行指定的代码,与主线程中的代码实现同时执行 还要解释一个概念:多任务调度系统 每个应用程序由操作系统分配的短暂的时间片(Timeslice)轮流使用CPU,由于CPU对每个时间片的处理速度非常快,

iOS多线程编程--NSOperation(转)

这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github.com/wangdachui/multithreading.git 1. NSOperation简介 NSOperation是苹果提供给我们的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更简单易用.代码可读性也更高. NSOperation需要配合NSOp

iOS 多线程编程

参考文章: iOS多线程编程之NSThread的使用http://blog.csdn.net/totogo2010/article/details/8010231 iOS多线程编程之NSOperation和NSOperationQueue的使用http://blog.csdn.net/totogo2010/article/details/8013316 iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用http://blog.csdn.net/totogo2010

iOS多线程编程——浅谈GCD

GCD对于iOS开发者来说肯定不陌生,他和NSThread,NSOperation一起作为iOS开发中主要的三种多线程实现方法,而GCD是最最底层的,所以对于作为一个iOSer,GCD是必须掌握的. 我通过对于以下两篇文章的阅读,基本上掌握了GCD的基本使用方法.所以首先感谢两位作者. GCD 深入理解:第一部分 iOS多线程开发--GCD的使用与多线程开发浅析(二) 一.基本概念 对于新手来说,最常见同时最容易搞混的的莫过于GCD中的一些基本概念了. 并行与并发(Parallelism &&am

iOS多线程——GCD篇

什么是GCD GCD是苹果对多线程编程做的一套新的抽象基于C语言层的API,结合Block简化了多线程的操作,使得我们对线程操作能够更加的安全高效. 在GCD出现之前Cocoa框架提供了NSObject类的 performSelectorInBackground:withObject performSelectorOnMainThread 方法来简化多线程编程技术. GCD可以解决以下多线程编程中经常出现的问题:1.数据竞争(比如同时更新一个内存地址) 2.死锁(互相等待) 3.太多线程导致消耗