iOS多线程学习笔记

iOS多线程

这里是资源地址

几种常用的多线程:

NSThread

可以直接控制线程对象,可以获取当前线程类,可以知道当前线程的各种属性。

用法:

//创建
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:nil];

//启动
[thread start];
//创建并自动启动
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:nil];
//使用NSObject的方法创建并自动启动
[self performSelectorInBackground:@selector(run:) withObject];
GCD

他是苹果为多核的并行运算提出的解决方案,他会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。用的比较多。

任务队列

任务:即操作,你想要干什么,说白了就是一段代码,在GCD中就是一个Blcok,所以添加任务十分方便。

任务有两种方式:同步执行异步执行,他们之间的区别:

同步操作,会阻塞当前线程并等待block中的任务执行完毕,然后当前线程才会继续往下运行。

异步操作,当前线程会直接往下执行,不会阻塞当前线程。

队列:用于存放任务。一共有两种队列,串行队列并行队列,他们的区别:

串行队列,放到串行队列的任务,GCD会FIFO的取出来一个,执行一个,然后取下一个,这样一个一个的执行。

并行队列,放到并行队列的任务,GCD也会FIFO的取出来,他取出一个就会放到别的线程,然后再取出一个又放到另一个线程。这样由于取的动作很快,忽略笔记,看起来所有的任务都是一起执行的。不过需要注意,GCD会根据系统资源控制并行数量,所以如果任务很多,他并不会让所有任务同时执行。

创建队列

  • 主队列
//创建主队列
dispatch_queue_t queue = dispatch_get_main_queue();
  • 自己创建的队列

其中第一个参数是标识符,用于DEBUG的时候标识唯一的队列,可以为空。第二个参数用来表示创建的队列是串行还是并行,传入DISPATCH_QUEUE_SERIALNULL表示创建串行队列。传入DISPATCH_QUEUE_CONCURRENT表示创建并行队列。

//串行队列
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL);
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);

//并行队列
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT);
  • 全局并行队列:只要是并行任务一般都加入到这个队列。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

创建任务

  • 同步任务:会阻塞当前线程(SYNC)
dispatch_sync(<#queue#>,^{
    //code here
    NSLog(@"%@",[NSThread currentThread]);
});
  • 异步任务:不会阻塞线程(ASYNC)
dispatch_async(<#queue#>,^{
    //code here
    NSLog(@"%@",[NSThread currentThread]);
});

队列组

队列组可以将很多队列添加到一个组里,这样的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。

//创建队列组
dispatch_group_t group = dispatch_group_create();
//创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//多次使用队列组的方法执行任务
dispatch_group_async(group, dispatch_get_main_queue(),^{
    //code here

});

dispatch_group_async(group, queue,^{
    //code here

});

//都完成后会自动通知
dispatch_group_notify(group,dispatch_get_main_queue(),^{
    //code here
    NSLog(@"完成-%@",[NSThread currentThread]);
});
NSOperation和NSOperationQueue

NSOperation是苹果公司对GCD的封装,NSOperation和NSOperationQueue分别对应GCD的任务队列

操作步骤:

  1. 将要执行的任务封装到一个NSOperation对象中。
  2. 将此任务添加到一个NSOperationQueue对象中。

然后系统就会自动执行任务。

添加任务

NSOperation只是一个抽象类,所以不能封装任务。但他有2个子类用于封装任务。分别是NSINvocationOperation和1NSBlockOperation。创建一个operation后,需要start方法来启动任务,他会默认在当前队列同步执行。当然你也可以在中途取消一个任务,只需要调用cancel方法即可。

NSInvocationOperation

//创建NSInvocationOperation对象
NSInvocationOperation * opertation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

//开始执行
[operation start];

NSBlcokOperation

//创建NSBlcokOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@",[NSThread currentThtead]);
}];

//添加多个blcok
for (NSInteger i = 0;i < 5; i++) {
    [operation addExecutionBlock:^{
        NSLog(@"第%ld次:%@",i,[NSThread currentThread]);
    }];
}
//开始任务
[operation start];

创建队列

主队列

NSOperationQueue *queue = [NSOperationQueue mainQueue];

其他队列

因为主队列比较特殊,所以会单独有一个类方法来获得主队列。那么通过初始化产生的队列就是其他队列了,因为只有这两种队列,除了主队列,其他队列就不需要名字了。

//1.创建一个其他队列    
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
}];

//3.添加多个Block
for (NSInteger i = 0; i < 5; i++) {
    [operation addExecutionBlock:^{
        NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
    }];
}

//4.队列添加任务
[queue addOperation:operation];

NSOperationQueueGCD的队列 相比较就会发现,这里没有串行队列,那如果我想要10个任务在其他线程串行的执行怎么办?

这就是苹果封装的妙处,你不用管串行、并行、同步、异步这些名词。NSOperationQueue 有一个参数 maxConcurrentOperationCount 最大并发数,用来设置最多可以让多少个任务同时执行。当你把它设置为 1 的时候,他不就是串行了嘛!

NSOperationQueue 还有一个添加任务的方法,- (void)addOperationWithBlock:(void (^)(void))block; ,这是不是和 GCD 差不多?这样就可以添加一个任务到队列中了,十分方便。

NSOperation 有一个非常实用的功能,那就是添加依赖。比如有 3 个任务:A: 从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。这时就可以用到依赖了:

//1.任务一:下载图片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"下载图片 - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
}];

//2.任务二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"打水印   - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
}];

//3.任务三:上传图片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"上传图片 - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
}];

//4.设置依赖
[operation2 addDependency:operation1];      //任务二依赖任务一
[operation3 addDependency:operation2];      //任务三依赖任务二

//5.创建队列并加入任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值