iOSh中多线程的使用

来源:互联网 发布:番茄鸡蛋打卤面 知乎 编辑:程序博客网 时间:2024/06/05 08:39

一、什么是多线程

1.    每一个进程都是一个应用程序,都有独立的内存空间,一般来说一个应用程序存在一个进程,但也有多个进程的情况。

2.    同一个进程中的线程共享内存中内存和资源。

3.    线程处理方式通过堆栈的形式来处理的,先进后出。放在堆内存里面管理

4.    每一个程序如果要运行,它都会创建一个主线程(每个程序都有一个主线程),程序启动时创建(调用main来启动)。

5.    每一个程序只有一个进程,但是在一个进程里面有多个线程。(也有1个线程的情况),进程相当于是一个容器,在这个容器里面装了多个进程,线程是在运行的,它可以去调用函数调用代码。

6.    主线程的生命周期和应用程序绑定的,程序退出(结束)时,主线程也就停止了。

7.    多线程技术表示,一个应用程序有多个线程,使用多线程能够提供CPU的使用率,防止主线程堵塞

8.    任何有可能堵塞主线程的任务不要在主线程执行(访问网络)

9.    进入后台时,主线程就会被挂起(程序退出时,主线程会被退出)

10.    每个线程相当于是一个路径,多线程相当于是多个分支的路径,由主路径(主线程)分支出来

11.    4和CPU就是多线程任务同时处理的


二、使用多线程的目的是什么

1. 引入多线程的主要目的是对大量任务进行有序的管理。通过多个任务的混合使用,可以更有效地利用计算机资源,避免主线程阻塞。

2. 比如在加载网络图片的时候,如果加载网络图片的过程用主线程来加载就会导致主线程堵塞,因为图片正在加载过程中正在使用主线程,这个时候无法操作其他了,所以这个时候可以让加载图片的操作让子线程去异步加载。


三、ios中有哪几种多线程方式

1. NSObject中的performSelectorInBackground方法

//通过NSObject的performSelectorInBackground多线程方法来异步请求图片,此方法最为简单。downLoadImage是后台(子线程)执行的方法[self performSelectorInBackground:@selector(downLoadImage) withObject:nil];

2. NSThread

// 优点:在所有的多线程实现方式中最轻量级,可以按照需求任意控制thread对象 即:线程的加锁等操作// 缺点:控制太繁琐 不能自己控制线程安全    // NSThread 的一个对象 就代表一个线程    NSThread *thread = [[NSThread alloc]initWithTarget:selfselector:@selector(btnUpClicked:)object:nil];    [thread start];

3. NSOperationQueue

    // 优点:能够自己管理 线程安全 能够合理的安排线程 降低系统的开销 提高对线程的利用率    // 缺点:可读性差 写起来比较繁琐    NSOperationQueue *queue = [[NSOperationQueue alloc]init];    // 设置最大并发数    [queue setMaxConcurrentOperationCount:2];    NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];    [queue addOperation:op];

4. GCD(比较常用,多核CPU的情况下建议使用此方式)

4.1  一般用法

    // GCD 是基于队列的 多线程实现方式    // 队列的类型    // 1.并行: 多个任务同时执行 Concurrent    // 2.串行: 依次执行任务(同一事件只执行一个任务) Serial         // 自己创建一个队列    // 参数1:给队列起个名字    // 参数2:选择队列的类型 DISPATCH_QUEUE_CONCURRENT(串行)     dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);    // 使用队列      // 参数1: 在哪个队列执行代码      // 参数2: 要执行的代码      dispatch_async(queue, ^{        [self downLoadImage];  //回调    });

4.2 高级用法

  // 系统定义了5个队列    // 1. 一个串行队列  主队列作用 : 管理主线程的相关事务         // 获得主队列    dispatch_queue_t mainQueue = dispatch_get_main_queue();    // 在主队列执行任务//    dispatch_async(mainQueue, ^{//        [self btnUpClicked:nil];//    });              // 2. 4个并行队列 (并行队列)    // 参数1: 选择队列的优先级    // 参数2: 给未来使用 一般填0    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//    dispatch_async(globalQueue, ^{//        [self btnUpClicked:nil];//    });         // 高端使用    // 1.全局队列获取数据 回到主队列将数据加载到视图上//    dispatch_async(globalQueue, ^{//       //        // 全局队列(子线程)获取数据//        NSString *str = @"htt://www.baidu.com";//        NSURL *url = [NSURL URLWithString:str];//        //        NSData *data = [NSData dataWithContentsOfURL:url];//        UIImage *image = [UIImage imageWithData:data];//        //        // 返回主线程 加载UI/更新UI//        dispatch_async(mainQueue, ^{//           //            UIImageView *imageView = [[UIImageView alloc] init];//            // 给视图赋值//            imageView.image = image;//            //        });//    });         // 2.一段代码只执行依次    // 大部分的时候 都在单例方法中使用    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        NSLog(@"只执行依次");    });         // 3.一段代码执行多次 (全局队列有效)    // 参数1: 执行多少次    // 参数2: 在哪个队列有效    // 参数3: 要执行的内容    dispatch_apply(4, globalQueue, ^(size_t a) {        NSLog(@"%zu", a);    });         // 4.定时    // 参数1: 间隔几秒    // 参数2: 执行的内容    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        NSLog(@"=====");    });


四、代码示例

//加载网络图片时候的例子

- (void)loadImageQueueInit{    //*****************1. 通过队列多线程来异步加载图片*****************    /*    NSOperationQueue *queue = [[NSOperationQueue alloc]init];    NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];    [queue addOperation:op];     */         //**********2. 通过NSObject的performSelectorInBackground多线程方法来异步请求图片**********//     //[self performSelectorInBackground:@selector(downLoadImage) withObject:nil];             //***************3. 通过GCD的方式创建一个新的线程来异步加载图片***************//    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue, ^{        [self downLoadImage];  //回调    });}- (void)downLoadImage{    NSURL  *imageURL = [NSURL URLWithString:self.figureurl];    imageData = [NSData dataWithContentsOfURL:imageURL];    [_pathCover setAvatarImage:[UIImage imageWithData:imageData]];}
0 0
原创粉丝点击