ios多线程(NSThread、GCD、NSOperation)

ios中得多线程技术主要使用3种:NSThread、NSOperation和GCD

  一、NSThread: 最轻量级方法,但是不安全需要手动加锁,需要自己管理生命周期

    NSThread的使用方法有2种:   

// 第一种,需要start
1 NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(btnClick) object:nil];
2     [th1 setName:@"线程1"];
3     [th1 start];
// 第二种
1 [NSThread detachNewThreadSelector:@selector(btnClick) toTarget:self withObject:nil];

因为NSThread使用不安全,我们需要给它加锁(主要的实现代码):

@property (nonatomic,assign) NSInteger fruits;
@property (nonatomic,strong) NSLock *lock;
- (void)viewDidLoad
{
    [super viewDidLoad];

    _lock = [[NSLock alloc] init];
    _fruits = 50;
}

- (void)btnClick
{
    @synchronized(_lock){ // 加锁
        
        while (_fruits > 0) {
            
            NSLog(@"当前线程为:%@ , 剩余票数为:%d",[NSThread currentThread], _fruits);
            
            _fruits--;
        }
    }
}

二、GCD:(Grand Central Dispatch)是一种多核编码技术,用纯C语言编写。

  异步:具备开启线程的功能

  同步:不具备开启线程的功能

  并行队列:多个任务可以同时执行

  串行队列:执行完一个任务后再执行下一个任务

  下面来进行用代码说明:

// 自定义异步方法
- (void)async:(dispatch_queue_t)queue
{
    // 异步执行
    dispatch_async(queue, ^{
        
        NSLog(@"im1-%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        
        NSLog(@"im2-%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        
        NSLog(@"im3-%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        
        NSLog(@"im4-%@",[NSThread currentThread]);
    });

}
// 自定义同步方法
- (void)sync:(dispatch_queue_t)queue
{
    // 同步执行
    dispatch_sync(queue, ^{
        
        NSLog(@"im1-%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        
        NSLog(@"im2-%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        
        NSLog(@"im3-%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        
        NSLog(@"im4-%@",[NSThread currentThread]);
    });

}

调用异步执行方法

 // 创建一个全局并行队列
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     
 // 异步执行
  [self async:queue];

最终的结果为:开启了四个线程,并且执行顺序是不定

2015-04-02 16:29:20.438 GCD[4398:1f07] im3-<NSThread: 0x7177ee0>{name = (null), num = 5}
2015-04-02 16:29:20.432 GCD[4398:1303] im1-<NSThread: 0x7177d70>{name = (null), num = 3}
2015-04-02 16:29:20.440 GCD[4398:4307] im4-<NSThread: 0x7178490>{name = (null), num = 6} 2015-04-02 16:29:20.432 GCD[4398:1a03] im2-<NSThread: 0x75429f0>{name = (null), num = 4}
1 // 创建一个全局串行队列
2     dispatch_queue_t queue = dispatch_queue_create("wys", NULL);
3     
4     // 异步执行
5     [self async:queue];

最终的结果为:开启了一个线程,执行顺序为从上往下依次执行

2015-04-02 16:32:19.415 GCD[4442:1303] im1-<NSThread: 0x71631a0>{name = (null), num = 3}
2015-04-02 16:32:19.428 GCD[4442:1303] im2-<NSThread: 0x71631a0>{name = (null), num = 3}
2015-04-02 16:32:19.437 GCD[4442:1303] im3-<NSThread: 0x71631a0>{name = (null), num = 3}
2015-04-02 16:32:19.450 GCD[4442:1303] im4-<NSThread: 0x71631a0>{name = (null), num = 3}

调用主队列执行方法:

1 // 创建主队列
2     dispatch_queue_t queue = dispatch_get_main_queue();
3     
4     // 异步执行
5     [self async:queue];

最终的结果为:顺序执行并且不开启线程,在主线程中执行、

2015-04-02 16:35:45.320 GCD[4484:c07] im1-<NSThread: 0x71560c0>{name = (null), num = 1}
2015-04-02 16:35:45.333 GCD[4484:c07] im2-<NSThread: 0x71560c0>{name = (null), num = 1}
2015-04-02 16:35:45.339 GCD[4484:c07] im3-<NSThread: 0x71560c0>{name = (null), num = 1}
2015-04-02 16:35:45.347 GCD[4484:c07] im4-<NSThread: 0x71560c0>{name = (null), num = 1}

// 创建主队列

dispatch_queue_t queue = dispatch_get_main_queue();

NSLog(@"start");

// 同步执行

[self sync:queue];

NSLog(@"end");

最终的结果为:执行到start就卡住了,不能往下执行

1 2015-04-02 16:38:12.856 GCD[4514:c07] start

调用同步执行方法:

1 // 创建全局并行队列2     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3     
4     // 同步执行
5     [self sync:queue];

最终的结果为:不开启线程,并且顺序执行,直接主线程执行

2015-04-02 16:41:27.448 GCD[4555:c07] im1-<NSThread: 0x71133c0>{name = (null), num = 1}
2015-04-02 16:41:27.458 GCD[4555:c07] im2-<NSThread: 0x71133c0>{name = (null), num = 1}
2015-04-02 16:41:27.468 GCD[4555:c07] im3-<NSThread: 0x71133c0>{name = (null), num = 1}
2015-04-02 16:41:27.472 GCD[4555:c07] im4-<NSThread: 0x71133c0>{name = (null), num = 1}
1 // 创建串行队列
2     dispatch_queue_t queue = dispatch_queue_create("wys", NULL);
3     
4     // 同步执行
5     [self sync:queue];

最终的结果为:不开启线程,并且顺序执行,直接主线程执行

2015-04-02 16:43:40.609 GCD[4589:c07] im1-<NSThread: 0x713e570>{name = (null), num = 1}
2015-04-02 16:43:40.621 GCD[4589:c07] im2-<NSThread: 0x713e570>{name = (null), num = 1}
2015-04-02 16:43:40.626 GCD[4589:c07] im3-<NSThread: 0x713e570>{name = (null), num = 1}
2015-04-02 16:43:40.634 GCD[4589:c07] im4-<NSThread: 0x713e570>{name = (null), num = 1}

多线程之间的通信:UI界面的更新一定要在主线程中执行

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 全局并行队列异步执行

NSLog(@"全局并行队列异步执行 - %@",[NSThread currentThread]);

// 获取网络图片数据

NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";

NSURL *url = [NSURL URLWithString:str];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

dispatch_async(dispatch_get_main_queue(), ^{ // 主线程异步执行

NSLog(@"主线程异步执行 - %@",[NSThread currentThread]);

// 更新界面

[_im1 setImage:image];

});

});

最终的结果为:

2015-04-03 11:37:08.513 GCD[1095:1303] 全局并行队列异步执行 -<NSThread: 0x754c530>{name = (null), num = 3}
2015-04-03 11:37:10.657 GCD[1095:c07] 主线程异步执行 -<NSThread: 0x7132c80>{name = (null), num = 1}

利用多线程来实现延时执行:

1、利用GCD

double delayInSeconds = 2.0; // 延时时长

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // 在主线程中执行

NSLog(@"%@",[NSThread currentThread]);

// 更新界面

[_im1 setImage:image];

});

2、利用此方法,performSelector为你要调用的方法,withObject为你要传得值,afterDelay为延时时长

1 [self performSelector:@selector(downLoad) withObject:nil afterDelay:0.5f];

队列组:

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_async(group, queue, ^{

// 代码1

});

dispatch_group_async(group, queue, ^{

// 代码2

});

dispatch_group_notify(group, queue, ^{

// 执行完代码1和代码2后,再执行此方法

});


三、NSOperation:基于GCD,能控制最大并发线程数,主要有2个类:NSInvocationOperation和NSBlockOperation

  其步骤为: 创建队列、添加操作、将操作添加到队列

  A、NSInvocationOperation:

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

{

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

NSInvocationOperation *invo = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(buy) object:nil];

[queue addOperation:invo];

}

- (void)buy

{

NSLog(@"%@",[NSThread currentThread]);

}

最后的结果为:开启了一个线程

1 2015-04-03 14:58:54.060 op1[2631:1e07] <NSThread: 0x71a6de0>{name = (null), num = 3}

B、NSBlockOperation

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

NSBlockOperation *b1 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"111--%@",[NSThread currentThread]);

}];

NSBlockOperation *b2 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"222--%@",[NSThread currentThread]);

}];

NSBlockOperation *b3 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"333--%@",[NSThread currentThread]);

}];

[queue addOperation:b1];

[queue addOperation:b2];

[queue addOperation:b3];

最后的结果为:开启了三个线程,自动异步执行

1 2015-04-03 15:15:59.897 op1[2798:1a03] 111--<NSThread: 0x7544fa0>{name = (null), num = 3}
2 2015-04-03 15:15:59.901 op1[2798:4307] 222--<NSThread: 0x71506f0>{name = (null), num = 4}
3 2015-04-03 15:15:59.902 op1[2798:1303] 333--<NSThread: 0x7545e60>{name = (null), num = 5}

设置依赖:

1 // 设置依赖 ,b2依赖b1,b3依赖b2,所以执行顺序为,b1->b2->b3
2     [b2 addDependency:b1];
3     [b3 addDependency:b2];

设置队列的最大并发数量:

1 // 设置最大并发(最多同时并发执行3个任务)
2     queue.maxConcurrentOperationCount = 2;


C、主队列

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[queue addOperationWithBlock:^{

NSLog(@"-------%@",[NSThread currentThread]);

// 获取网络图片数据

NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";

NSURL *url = [NSURL URLWithString:str];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ // 主队列

NSLog(@"******%@",[NSThread currentThread]);

// 更新界面

[_im1 setImage:image];

}];

}];

最后的结果为:

1 2015-04-03 15:27:16.077 op1[2916:1c03] -------<NSThread: 0x71613e0>{name = (null), num = 3}2 2015-04-03 15:27:17.593 op1[2916:c07] ******<NSThread: 0x7134fa0>{name = (null), num = 1} // 主队列

时间: 2024-10-13 14:16:03

ios多线程(NSThread、GCD、NSOperation)的相关文章

iOS多线程 NSThread/GCD/NSOperationQueue

http://www.cnblogs.com/kenshincui/p/3983982.html iOS开发系列--并行开发其实很容易 2014-09-20 23:34 by KenshinCui, 9738 阅读, 19 评论, 收藏,  编辑 --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种

iOS多线程(GCD NSOperation NSThread)

进程:进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 线程:1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行,比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行.1个线程中任务的执行是串行的,如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务,也就是说,在同一时间内,1个线程只能执行1个任务,比如在1个线程中下载3个文件(分别是文

iOS 多线程学习笔记 —— NSOperation

本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://blog.csdn.net/totogo2010/原创,欢迎转载分享.请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢! 这里对原作者的辛勤工作表示感谢! 1. 使用抽象的 NSOperation 的方式有两种: (1)用库定义好的子类: NSInvocationOperation 和 NSBlo

iOS多线程技术—自定义NSOperation

iOS多线程技术—自定义NSOperation 一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UITableViewController. // // YYViewController.h // 01-自定义Operation // // Created by apple on 14-6-26. // Copyright (c) 2014年 itcase. All rights reserved.

iOS多线程技术—GCD介绍

iOS多线程技术—GCD介绍 一.简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核.四核) GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 3.提示 (1)GCD存在于libdispatch.dylib这个库中,

iOS多线程技术—GCD的用法

iOS多线程技术—GCD的用法 一.主队列介绍 主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行. 提示:如果把任务放到主队列中进行处理,那么不论处理函数是异步的还是同步的都不会开启新的线程. 获取主队列的方式: 1 // 2 // YYViewController.m 3 // 12-GCD的基本使用(主队列) 4 // 5 // Created by 孔医己 on 14-6-25. 6 // Copyright (c) 2014

iOS多线程编程之NSOperation和NSOperationQueue的使用(转自容芳志专栏)

转自由http://blog.csdn.net/totogo2010/ 使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation. 另一种是继承NSOperation 如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似.和Java的Runnable一样,NSOperation也是设计用来扩展的,只需继承重写NSOperation的一个方法main.相当与ja

多线程 NSThread GCD

ios多线程实现种类 NSThread NSOperationQueue NSObject GCD *************** 1.NSThread //线程 第一种 NSThread *thread1=[[NSThread alloc] initWithTarget:self selector:@selector(sum) object:nil]; // //    //给线程起名字 [email protected]"thread1"; //    //启动线程 [thread

iOS多线程开发之NSOperation - 快上车,没时间解释了!

一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强,很屌的是加入了操作依赖. 默认情况下,NSOperation单独使用时只能同步执行操作,并没有开辟新线程的能力,只有配合NSOperationQueue才能实现异步执行.讲到这里,我们不难发现GCD和NSOperation实现的方式很像,其实这更像是废话,NSOperation本身就是基于GCD的

iOS多线程编程之NSOperation和NSOperationQueue的使用

前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation. 另一种是继承NSOperation 如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似.和Java的Runnable一样,NSOperation也是设计用来扩展