ios学习iOS精华iOS开发技术讨论

iOS中你必须了解的多线程

2015-11-27  本文已影响5716人  J_mailbox

多线程概念详解

什么是进程?
什么是线程?
进程和线程之间的关系
什么是CPU?
多线程的原理
多线程优点
多线程的缺点
主线程
IOS中多线程的实现方案
方案 简介 语言 线程生命周期 使用频率
pthread <ul><li>一套通用的多线程API</li><li>适用于 Unix / Linux / Windows 等系统</li><li>跨平台\可移植</li><li>使用难度大</li></ul> C 程序员管理 几乎不用
NSThread <ul><li>使用更加面向对象</li><li>简单易用,可直接操作线程对象</li></ul> OC 程序员管理 偶尔使用
GCD <ul><li>旨在替代NSThread等线程技术</li><li>充分利用设备的多核</li></ul> C 自动管理 经常使用
NSOperation <ul><li>基于GCD(底层是GCD)</li><li>比GCD多了一些更简单实用的功能</li><li>使用更加面向对象</li></ul> OC 自动管理 经常使用
NSThread使用
创建线程的种方式
NSThread 是iOS提供的轻量级开发,使用起来也相对简单
为什么要使用NSThread ?
NSThread-Demo:
//点击下载图片
- (IBAction)downLoadButton:(id)sender {
    //通过NSThread对象方法
    //[self objectMethod];
    //通过NSThread类方法
    //[self classMethod];
    //通过NSObject的方法
    [self extendedMethod];
}

//通过NSObject的方法去下载图片
- (void)extendedMethod{
    //通过NSObject分类方法
   [self performSelectorInBackground:@selector(downLoadImage) withObject:nil];
   
}

//通过NSThread类方法去下载图片
- (void)classMethod{
    //NSThread类方法
    [NSThread detachNewThreadSelector:@selector(downLoadImage) toTarget:self withObject:nil];
}

//通过NSThread对象方法去下载图片
- (void)objectMethod{
    //创建一个程序去下载图片
    NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];
    NSLog(@"downLoadButton:%@",[NSThread currentThread]);//主线程
    //开启线程
    [thread start];
}

//下载图片
- (void)downLoadImage{
    //请求图片资源
    NSURL *url=[NSURL URLWithString:@"http://pic7.nipic.com/20100515/2001785_115623014419_2.jpg"];
    //模拟下载延迟
    [NSThread sleepForTimeInterval:10];
    //将资源转换为二进制
    NSData *data=[NSData dataWithContentsOfURL:url];
    NSLog(@"downLoadImage:%@",[NSThread currentThread]);//在子线程中下载图片
    //在主线程更新UI
    [self performSelectorOnMainThread:@selector(updateImage:) withObject:data waitUntilDone:YES];
    
}

//更新imageView
- (void)updateImage:(NSData *)data{
    NSLog(@"updateImage:%@",[NSThread currentThread]);//在主线程中更新UI
    //将二进制数据转换为图片
    UIImage *image=[UIImage imageWithData:data];
    //设置image
    self.imageView.image=image;
}

以上就是对NSThread三种使用的一个简单的Demo
线程状态
线程的属性(name)
线程的优先级(threadPriority)
栈区大小(stackSize)
是否是主线程(isMainThread)
线程间的通讯
GCD的使用
GCD 核心概念
  1. 任务添加到队列,并且指定执行任务的函数
  2. 任务使用 block 封装
    • 任务的 block 没有参数也没有返回值
  3. 执行任务的函数
    • 异步 dispatch_async
      • 不用等待当前语句执行完毕,就可以执行下一条语句
      • 会开启线程执行 block 的任务
      • 异步是多线程的代名词
    • 同步 dispatch_sync
      • 必须等待当前语句执行完毕,才会执行下一条语句
      • 不会开启线程
      • 在当前执行 block 的任务
  4. 队列 - 负责调度任务
    • 串行队列
      • 一次只能"调度"一个任务
      • dispatch_queue_create("queue", NULL);
    • 并发队列
      • 一次可以"调度"多个任务
      • dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    • 主队列
      • 专门用来在主线程上调度任务的队列
      • 不会开启线程
      • 主线程空闲时才会调度队列中的任务在主线程执行
      • dispatch_get_main_queue();
阶段性小结
- 队列的选择
实际开发中,线程数量如何决定?
同步 & 异步
NSThread-Demo
//点击屏幕调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSLog(@"touchesBegan开始执行");
    //同步调用
    [self start];
    
    //异步调用
    //[self performSelectorInBackground:@selector(start) withObject:nil];
    NSLog(@"touchesBegan执行结束");
}

//开始执行
- (void)start{
    NSLog(@"start开始执行");
    NSLog(@"start当前线程:%@",[NSThread currentThread]);
    //延迟5秒调用
    [NSThread sleepForTimeInterval:5];
    NSLog(@"start执行完毕");
}

执行以上代码,发现当同步的时候执行的结果为:
2015-11-26 18:17:29.621 GCD同步异步[1267:159851] touchesBegan开始执行
2015-11-26 18:17:29.621 GCD同步异步[1267:159851] start开始执行
2015-11-26 18:17:29.621 GCD同步异步[1267:159851] start当前线程:<NSThread: 0x7fec12e01780>{number = 1, name = main}
2015-11-26 18:17:34.627 GCD同步异步[1267:159851] start执行完毕
2015-11-26 18:17:34.627 GCD同步异步[1267:159851] touchesBegan执行结束

执行以上代码,发现当异步的时候执行的结果为:
2015-11-26 18:23:10.846 GCD同步异步[1282:163977] touchesBegan开始执行
2015-11-26 18:23:10.847 GCD同步异步[1282:163977] touchesBegan执行结束
2015-11-26 18:23:10.848 GCD同步异步[1282:164254] start开始执行
2015-11-26 18:23:10.848 GCD同步异步[1282:164254] start当前线程:<NSThread: 0x7fa778f0f0f0>{number = 2, name = (null)}
2015-11-26 18:23:15.849 GCD同步异步[1282:164254] start执行完毕
结论: 同步是从上到下有顺序的执行,异步则不是
GCD-Demo
//点击屏幕的时候调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //异步
    //[self asyncMethod];
    //同步
    [self syncMethod];
    
}

//异步的时候调用
- (void)asyncMethod{
    //获取全局队列
    dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
    //创建任务
    void(^task)()=^{
        NSLog(@"asyncMethod:%@",[NSThread currentThread]);
    };
    //执行任务
    dispatch_async(queue, task);
    
    NSLog(@"end");
}

//同步的时候调用
- (void)syncMethod{
    //获取全局队列
    dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
    //创建任务
    void(^task)()=^{
        NSLog(@"syncMethod:%@",[NSThread currentThread]);
    };
    //执行任务
    dispatch_sync(queue, task);
    
    NSLog(@"end");
}

执行以上代码,发现当同步的时候执行的结果为:
2015-11-26 18:40:55.419 GCD中的同步和异步[1361:177648] syncMethod:<NSThread: 0x7fa7d14036b0>{number = 1, name = main}
2015-11-26 18:40:55.419 GCD中的同步和异步[1361:177648] end
2015-11-26 18:40:55.667 GCD中的同步和异步[1361:177648] syncMethod:<NSThread: 0x7fa7d14036b0>{number = 1, name = main}
2015-11-26 18:40:55.667 GCD中的同步和异步[1361:177648] end
2015-11-26 18:40:55.926 GCD中的同步和异步[1361:177648] syncMethod:<NSThread: 0x7fa7d14036b0>{number = 1, name = main}
2015-11-26 18:40:55.927 GCD中的同步和异步[1361:177648] end

执行以上代码,发现当异步的时候执行的结果为:
2015-11-26 18:41:36.351 GCD中的同步和异步[1370:178492] asyncMethod:<NSThread: 0x7fc941e02a70>{number = 2, name = (null)}
2015-11-26 18:41:36.351 GCD中的同步和异步[1370:178425] end
2015-11-26 18:41:36.576 GCD中的同步和异步[1370:178425] end
2015-11-26 18:41:36.576 GCD中的同步和异步[1370:178492] asyncMethod:<NSThread: 0x7fc941e02a70>{number = 2, name = (null)}
2015-11-26 18:41:36.810 GCD中的同步和异步[1370:178425] end
2015-11-26 18:41:36.810 GCD中的同步和异步[1370:178492] asyncMethod:<NSThread: 0x7fc941e02a70>{number = 2, name = (null)}

和NSThread对比可以发现
使用GCD下载图片
//点击下载图片
- (IBAction)downLoadButton:(id)sender {
    //获取全局队列
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       //异步下载图片
        NSURL *url=[NSURL URLWithString:@"http://pic7.nipic.com/20100515/2001785_115623014419_2.jpg"];
        //将资源转换为二进制
        NSData *data=[NSData dataWithContentsOfURL:url];
        //将二进制转化为图片
        UIImage *image=[UIImage imageWithData:data];

        //获取主队列,更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            //给图片控件赋值
            self.imageView.image=image;
        });
    });
}

串行队列
串行队列特点:
队列创建
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
串行队列同步&异步Demo
//点击屏幕的时候调用

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //同步执行
    //[self syncMethod];
    //异步执行
    [self asyncMethod];
}
//同步
- (void)syncMethod{
    //创建队列
    dispatch_queue_t queue=dispatch_queue_create("同步", DISPATCH_QUEUE_SERIAL);
    //执行任务
    
    for (int i=0; i<6; i++) {
        NSLog(@"1--->%d",i);
        
        dispatch_sync(queue, ^{
            NSLog(@"2--->%d---%@",i,[NSThread currentThread]
                  );
        });
    }
    NSLog(@"end");
}
//异步
- (void)asyncMethod{
    //创建队列
    dispatch_queue_t queue=dispatch_queue_create("异步", DISPATCH_QUEUE_SERIAL);
    //执行任务
    
    for (int i=0; i<6; i++) {
        NSLog(@"1--->%d",i);
        
        dispatch_async(queue, ^{
            NSLog(@"2--->%d---%@",i,[NSThread currentThread]
                  );
        });
    }
    NSLog(@"end");
}

串行队列 同步执行结果:
2015-11-26 19:12:20.876 串行队列的同步和异步[1520:204175] 1--->0
2015-11-26 19:12:20.877 串行队列的同步和异步[1520:204175] 2--->0---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.877 串行队列的同步和异步[1520:204175] 1--->1
2015-11-26 19:12:20.877 串行队列的同步和异步[1520:204175] 2--->1---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.877 串行队列的同步和异步[1520:204175] 1--->2
2015-11-26 19:12:20.877 串行队列的同步和异步[1520:204175] 2--->2---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 1--->3
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 2--->3---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 1--->4
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 2--->4---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 1--->5
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] 2--->5---<NSThread: 0x7fe952c05820>{number = 1, name = main}
2015-11-26 19:12:20.878 串行队列的同步和异步[1520:204175] end

串行队列 异步执行结果:
2015-11-26 19:12:41.923 串行队列的同步和异步[1529:204751] 1--->0
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204751] 1--->1
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204829] 2--->0---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204751] 1--->2
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204829] 2--->1---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204751] 1--->3
2015-11-26 19:12:41.924 串行队列的同步和异步[1529:204829] 2--->2---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204751] 1--->4
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204829] 2--->3---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204751] 1--->5
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204829] 2--->4---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204751] end
2015-11-26 19:12:41.925 串行队列的同步和异步[1529:204829] 2--->5---<NSThread: 0x7fc99970bbe0>{number = 2, name = (null)}

并发队列
并发队列特点:
队列创建
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

并行队列同步&异步Demo
//点击屏幕的时候调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //同步
    //[self syncMethod];
    //异步
    [self asyncMethod];
}

//异步
- (void)asyncMethod{

    //并发队列
    dispatch_queue_t queue=dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //创建任务
    for(int i=0; i<6 ;i++ ){
        dispatch_async(queue, ^{
            NSLog(@"async--->%d---%@",i,[NSThread currentThread]);
        });
    }
    NSLog(@"end");
}

//同步
- (void)syncMethod{

    //并发队列
    dispatch_queue_t queue=dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //创建任务
    for(int i=0; i<6 ;i++ ){
        dispatch_sync(queue, ^{
            NSLog(@"sync--->%d---%@",i,[NSThread currentThread]);
        });
    }
    NSLog(@"end");
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

并行队列 同步执行结果:
2015-11-26 21:17:19.820 并发队列的同步与异步[1632:233685] sync--->0---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.820 并发队列的同步与异步[1632:233685] sync--->1---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.821 并发队列的同步与异步[1632:233685] sync--->2---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.821 并发队列的同步与异步[1632:233685] sync--->3---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.821 并发队列的同步与异步[1632:233685] sync--->4---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.821 并发队列的同步与异步[1632:233685] sync--->5---<NSThread: 0x7fd762400f70>{number = 1, name = main}
2015-11-26 21:17:19.822 并发队列的同步与异步[1632:233685] end

并行队列 异步执行结果:
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234351] end
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234532] async--->3---<NSThread: 0x7fa823c9a910>{number = 5, name = (null)}
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234425] async--->0---<NSThread: 0x7fa823f0e720>{number = 3, name = (null)}
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234423] async--->2---<NSThread: 0x7fa823e079f0>{number = 4, name = (null)}
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234533] async--->4---<NSThread: 0x7fa823e000b0>{number = 6, name = (null)}
2015-11-26 21:17:45.000 并发队列的同步与异步[1641:234424] async--->1---<NSThread: 0x7fa823d4d4e0>{number = 2, name = (null)}
2015-11-26 21:17:45.001 并发队列的同步与异步[1641:234534] async--->5---<NSThread: 0x7fa823f0a290>{number = 7, name = (null)}

全局队列
主队列
//点击屏幕的时候调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //全局队列同步执行
    [self global_queue_sync];
    //全局队列异步执行
    //[self global_queue_async];
    //主队列同步执行
    //[self main_queue_sync];
    //主队列异步执行
    //[self main_queue_async];
}
//主队列同步执行
- (void)main_queue_sync{
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    for (int i = 0; i < 10; ++i) {
        dispatch_sync(queue, ^{
            NSLog(@"main_queue_sync%@---->%d", [NSThread currentThread], i);
        });
    }
    NSLog(@"end");
}

//主队列异步执行
- (void)main_queue_async{
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    for (int i = 0; i < 10; ++i) {
        dispatch_async(queue, ^{
            NSLog(@"main_queue_async%@---->%d", [NSThread currentThread], i);
        });
    }
    NSLog(@"end");
}

//全局队列异步执行
- (void)global_queue_async{
    //获取全局队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);
    
    //执行任务
    for (int i = 0; i < 10; ++i) {
        dispatch_async(q, ^{
            NSLog(@"global_queue_async%@---->%d", [NSThread currentThread], i);
        });
    }
    NSLog(@"end");
}

//全局队列同步执行
- (void)global_queue_sync{
    //获取全局队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);
    
    //执行任务
    for (int i = 0; i < 10; ++i) {
        dispatch_sync(q, ^{
            NSLog(@"global_queue_sync%@---->%d", [NSThread currentThread], i);
        });
    }
    NSLog(@"end");
}

全局队列 同步执行结果:
2015-11-26 22:00:12.568 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->0
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->1
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->2
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->3
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->4
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->5
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->6
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->7
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->8
2015-11-26 22:00:12.569 全局队列与主队列[1895:266991] global_queue_sync<NSThread: 0x7fb871d069e0>{number = 1, name = main}---->9
2015-11-26 22:00:12.570 全局队列与主队列[1895:266991] end

全局队列 异步执行结果:
2015-11-26 22:01:01.565 全局队列与主队列[1908:268194] end
2015-11-26 22:01:01.566 全局队列与主队列[1908:268233] global_queue_async<NSThread: 0x7f97fb607e80>{number = 2, name = (null)}---->1
2015-11-26 22:01:01.566 全局队列与主队列[1908:268234] global_queue_async<NSThread: 0x7f97fb61f710>{number = 4, name = (null)}---->2
2015-11-26 22:01:01.566 全局队列与主队列[1908:268256] global_queue_async<NSThread: 0x7f97fb63bec0>{number = 5, name = (null)}---->3
2015-11-26 22:01:01.566 全局队列与主队列[1908:268257] global_queue_async<NSThread: 0x7f97fb7127d0>{number = 6, name = (null)}---->4
2015-11-26 22:01:01.566 全局队列与主队列[1908:268232] global_queue_async<NSThread: 0x7f97fb70bde0>{number = 3, name = (null)}---->0
2015-11-26 22:01:01.566 全局队列与主队列[1908:268233] global_queue_async<NSThread: 0x7f97fb607e80>{number = 2, name = (null)}---->5
2015-11-26 22:01:01.566 全局队列与主队列[1908:268234] global_queue_async<NSThread: 0x7f97fb61f710>{number = 4, name = (null)}---->6
2015-11-26 22:01:01.566 全局队列与主队列[1908:268258] global_queue_async<NSThread: 0x7f97fb442510>{number = 7, name = (null)}---->7
2015-11-26 22:01:01.566 全局队列与主队列[1908:268256] global_queue_async<NSThread: 0x7f97fb63bec0>{number = 5, name = (null)}---->8
2015-11-26 22:01:01.567 全局队列与主队列[1908:268257] global_queue_async<NSThread: 0x7f97fb7127d0>{number = 6, name = (null)}---->9

主队列 同步执行结果:
主队列和主线程相互等待会造成死锁,程序直接卡死
主队列 异步执行结果:
2015-11-26 22:02:09.057 全局队列与主队列[1935:269576] end
2015-11-26 22:02:09.058 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->0
2015-11-26 22:02:09.058 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->1
2015-11-26 22:02:09.058 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->2
2015-11-26 22:02:09.058 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->3
2015-11-26 22:02:09.058 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->4
2015-11-26 22:02:09.059 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->5
2015-11-26 22:02:09.059 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->6
2015-11-26 22:02:09.059 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->7
2015-11-26 22:02:09.059 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->8
2015-11-26 22:02:09.087 全局队列与主队列[1935:269576] main_queue_async<NSThread: 0x7fadd850a320>{number = 1, name = main}---->9

NSOperation
NSOperation-Demo
//当点击屏幕的时候调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //创建url
    NSURL *url=[NSURL URLWithString:@"http://pic7.nipic.com/20100515/2001785_115623014419_2.jpg"];
    //将资源转换为二进制
    NSData *data=[NSData dataWithContentsOfURL:url];
    //创建operation
    NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage:) object:data];
    //执行操作
    [operation start];
}

- (void)downLoadImage:(NSData *)data{
    //将二进制转化为图片
    UIImage *image=[UIImage imageWithData:data];
    //显示图片
    self.imageView.image=image;
    
}

将任务添加到队里中执行
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    //创建队列
    NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
    //创建任务
    NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:nil];
        NSLog(@"1--->%@",[NSThread currentThread]);
    //将任务添加到队列中
    [operationQueue addOperation:operation];
}

//子线程中下载图片
- (void)downLoadImage{
    //创建url
    NSURL *url=[NSURL URLWithString:@"http://pic7.nipic.com/20100515/2001785_115623014419_2.jpg"];
    //将资源转换为二进制
    NSData *data=[NSData dataWithContentsOfURL:url];
    NSLog(@"2--->%@",[NSThread currentThread]);
    //将二进制转化为tup
    UIImage *image=[UIImage imageWithData:data];
    [self performSelectorOnMainThread:@selector(updateImage:) withObject:image waitUntilDone:YES];
}

//主线程中更新图片
- (void)updateImage:(UIImage *)image{
     NSLog(@"3--->%@",[NSThread currentThread]);
    self.imageView.image=image;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

总结:无论使用何种方式进行多线程开发,都应该遵循一定的规则(尽可能将比较耗时比如去网络下载资源的操作放到子线程中执行),注重程序的执行效率以及用户的体验合理的使用多线程(线程虽好,可不要乱用噢).

以上Demo下载路径:https://github.com/chengaojian**

以上就是多线程中常用的一些介绍,由于时间比较仓促,很多例子都是现写,如果代码中存在错误,还请指出,谢谢.

上一篇 下一篇

猜你喜欢

热点阅读