iOS开发之多线程
本文章博主和大家一块学习多线程,很自然就涉及到线程和进程,然后涵括NSThread、GCD、NSOperation!然后就是最牛叉的RunLoop和Runtime。
一、线程与进程
进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发。
线程是进程的子任务,是CPU调度和分配的基本单位,用于保障程序执行的实时性,实现进程内部的并发。
区别:
- 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。
- 进程是资源分配的最小单位,线程是CPU调度的最小单位
- 进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。
- 进程间不会相互影响 ;线程:一个线程挂掉将导致整个进程挂掉
- 线程之间的通信更加方便,同一个进程下线程共享全局变量,静态变量等数据。
二、多线程
多线程的优点和缺点
- 优点
1.能适当的提高程序的执行效率
2.能适当提高资源利用率(CPU内存利用率) - 缺点
1.开启线程需要占用一定的内存空间,如果开启大量的线程,则会占用大量的内存空间,降低程序的性能。
2.线程越多,CUP在调度线程的开销就越大。
3.程序设计更加复杂,比如线程之间的通信,多线程的数据共享。
多线程的应用
1.使用单利模式时,可以使用GCD
2.耗时操作放入子线程处理,完成后回主线程显示。
3.从数据库读取大量数据,可开辟子线程操作。
4.处理音频、视频数据时,在子线程处理。
5.数据同步操作。
三、容易混淆的4个术语
同步和异步主要影响:能不能开启新的线程。
1.同步:只是在当前线程中执行任务,不具备开启新线程的能力。
2.异步:可以在新的线程中执行,具备开启新线程的能力。
并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行。
串行:一个任务执行完毕后,再执行下一个任务。
四、NSThread、NSOperation、GCD
1.NSThread
1)通过NSThread的对象方法(动态创建)
2)通过NSThread的类方法(静态创建)
NSThread的线程管理
- 线程创建
- 线程开启
- 线程取消
- 线程关闭
- 线程暂停
- 设置线程优先级
NSThread的线程通信
- 指定当前线程执行操作
- (在其他线程中)指定主线程执行操作
- 在主线程中)指定其他线程执行操作
2.NSOperation
2.1 NSOperation 基本使用
在iOS开发中,为了提升用户体验,我们通常会将操作耗时的操作放在主线程之外的线程进行处理。对于正常的简单操作,我们更多的选择代码更少的GCD,让我们专注于自己的业务逻辑开发。NSOperation在iOS4后也基于GCD实现,但是对于GCD来说可控性更强,并且可以加入操作依赖。
(1) 相关概念
NSOperation是对GCD的封装,其中有两个核心概念【队列+操作】
1.NSOperation本身是抽象类,只能有它的子类。
2.两大子类分别是:NSBlockOperation、NSInvocationOperation,当然你也可以自定义继承自NSOperation的类。
(2)基本使用
- 实例化NSOperation的子类,绑定执行的操作。
- 创建NSOperationQueue队列,将NSOperation实例添加进来。
- 系统会自动将NSOperationQueue队列中检测取出和执行NSOperation的操作。
NSInvocationOperation类
// 01 NSInvocationOperation创建线程
/*
第一个参数:目标对象
第二个参数:该操作要调用的方法,最多接受一个参数
第三个参数:调用方法传递的参数,如果方法不接受参数,那么该值传nil
*/
- (void) method1 {
NSString * imageUrl = @"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=482494819,3150422682&fm=200&gp=0.jpg";
NSInvocationOperation * invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImageSource:) object:imageUrl];
// [invocationOperation start];
//一旦执行操作,就会调用target的sel方法, 默认情况下调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作,只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:invocationOperation];
}
//更新imageView
- (void)updateImage:(NSData *)data{
//在主线程中更新UI
//将二进制数据转换为图片
UIImage *image=[UIImage imageWithData:data];
//设置image
self.imageView.image=image;
}
NSBlockOperation类
- 创建NSBlockOperation对象
- 通过addExecutionBlock:方法添加更多的操作
队列的取消、暂停、和恢复
// 恢复队列,继续执行
// self.queue.suspended = NO;
// 暂停(挂起)队列,暂停执行
// self.queue.suspended = YES;
// 取消队列的所有操作
[self.queue cancelAllOperations];
操作依赖
NSOperation之间可以设置依赖来保证执行顺序
不添加依赖之前op1、op2、op3的顺序是随机的
在不同queue的NSOperation之间创建依赖关系
在不加依赖之前,op1和op2的执行顺序是随机的,添加依赖后op2会在op1之后执行。
线程间的通讯
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self updateImage:data];
}];
3.GCD
3.1基本概念
全称是Grand Central Dispatch,即:强大的中枢调度器,它是纯C语言的,提供了非常多强大的函数。
3.2GCD的优势:
GCD是苹果公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(比如双核、四核)
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
3.3GCD的使用步骤:
-
指定任务:确定想要做的事
-
将任务添加到队列中:GCD会自动将队列中的任务取出,放到对应的线程中执行,任务的取出遵循队列的FIFO原则:先进先出,后进后出。
3.4GCD的队列
3.4.1 GCD的队列可以分为2大类型:
1.并发队列(Current Dispatch Queue)
2.串行队列(Serial Dispatch Queue)
3.4.2 使用dispatch_queue_create函数创建队列
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
其中:const char *label 列队列的名称
dispatch_queue_attr_t attr 队列的类型
创建一个并发队列
dispatch_queue_t queue1 = dispatch_queue_create("myQueue1", DISPATCH_QUEUE_CONCURRENT);
创建一个串行队列
dispatch_queue_t queue2 = dispatch_queue_create("myQueue2", DISPATCH_QUEUE_SERIAL);
GCD默认意境提供了全局的并发队列,供整个应用使用,可以无需手动创建
使用dispatch_get_global_queue 函数获得全局并发队列
//获得全局的并发队列
dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
其中:第一个参数代表全局并发队列的优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 --》 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 --》 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) --》 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN --》 后台
第二个参数标记:是为了未来使用保留的!所以这个参数应该永远指定为0
GCD中获得串行有2种途径
1.使用dispatch_queue_create 创建串行队列,创建串行队列(队列类型传递NULL或者DISPATCH_QUEUE_SERIAL)
dispatch_queue_t queue4 = dispatch_queue_create("com.520.queue", NULL);
2.使用主队列 (跟主线程相关联的队列),主队列时GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放在主线程中执行,dispatch_get_main_queue()获得主队列
dispatch_queue_t queue5 = dispatch_get_main_queue();
3.4.3 应用
3.4.3.1 串行队里
3.4.3.2.并发队列(Concurrent Dispatch Queue)
//
// ViewController.m
// TestThread
//
// Created by denggaoqiang on 2022/9/10.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self example14];
}
- (void)example1 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"当前同步任务1一-------%@",[NSThread currentThread]);
sleep(3);
});
NSLog(@"1111");
dispatch_sync(queue, ^{
NSLog(@"当前同步任务2一-------%@",[NSThread currentThread]);
sleep(2);
});
NSLog(@"2222");
dispatch_sync(queue, ^{
NSLog(@"当前同步任务3一-------%@",[NSThread currentThread]);
sleep(1);
});
NSLog(@"走到这里了");
/** 打印结果
当前同步任务1
1111
当前同步任务2
2222
当前同步任务3
走到这里了
*/
}
- (void)example2 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
sleep(5);
NSLog(@"当前异步任务1一-------%@",[NSThread currentThread]);
});
NSLog(@"1111");
dispatch_async(queue, ^{
sleep(2);
NSLog(@"当前异步任务2一-------%@",[NSThread currentThread]);
});
NSLog(@"2222");
dispatch_async(queue, ^{
sleep(1);
NSLog(@"当前异步任务3一-------%@",[NSThread currentThread]);
});
NSLog(@"走到这里了");
/** 打印结果
1111
2222
走到这里了
当前异步任务1
当前异步任务2
当前异步任务3
*/
}
- (void)example3 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"当前同步任务1一-------%@",[NSThread currentThread]);
});
NSLog(@"1111");
dispatch_async(queue, ^{
NSLog(@"当前异步任务2开始一-------%@",[NSThread currentThread]);
sleep(10);
NSLog(@"当前异步任务2结束一-------%@",[NSThread currentThread]);
});
NSLog(@"2222");
dispatch_sync(queue, ^{
sleep(2);
NSLog(@"当前同步任务3一-------%@",[NSThread currentThread]);
});
NSLog(@"3333");
dispatch_async(queue, ^{
sleep(1);
NSLog(@"当前异步任务4一-------%@",[NSThread currentThread]);
});
NSLog(@"走到这里了");
/** 打印结果
当前同步任务1
1111
2222
当前异步任务2开始
当前异步任务2结束
当前同步任务3
3333
走到这里了
当前异步任务4
*/
}
- (void)example4 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
sleep(5);
NSLog(@"当前同步任务1一-------%@",[NSThread currentThread]);
});
NSLog(@"1111");
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"当前同步任务2一-------%@",[NSThread currentThread]);
});
NSLog(@"2222");
dispatch_sync(queue, ^{
sleep(1);
NSLog(@"当前同步任务3一-------%@",[NSThread currentThread]);
});
NSLog(@"走到这里了");
/** 打印结果
当前同步任务1
1111
当前同步任务2
2222
当前同步任务3
走到这里了
*/
}
- (void)example5 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
sleep(5);
NSLog(@"当前同步任务1一-------%@",[NSThread currentThread]);
});
NSLog(@"1111");
dispatch_async(queue, ^{
sleep(8);
NSLog(@"当前异步任务2一-------%@",[NSThread currentThread]);
});
NSLog(@"2222");
dispatch_async(queue, ^{
sleep(3);
NSLog(@"当前同步任务3一-------%@",[NSThread currentThread]);
});
NSLog(@"3333");
dispatch_async(queue, ^{
sleep(1);
NSLog(@"当前异步任务4一-------%@",[NSThread currentThread]);
});
NSLog(@"走到这里了");
/** 打印结果
1111
2222
3333
走到这里了
当前异步任务4
当前异步任务3
当前异步任务1
当前异步任务2
*/
}
- (void)example6 {
dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"当前同步任务1一-------%@",[NSThread currentThread]);
});
NSLog(@"1111");
dispatch_async(queue, ^{
sleep(8);
NSLog(@"当前异步任务2一-------%@",[NSThread currentThread]);
});
NSLog(@"2222");
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"当前同步任务3一-------%@",[NSThread currentThread]);
});
NSLog(@"3333");
dispatch_async(queue, ^{
sleep(1);
NSLog(@"当前异步任务4一-------%@",[NSThread currentThread]);
});
NSLog(@"走到这里了");
/** 打印结果
当前同步任务1
1111
2222
当前同步任务3
3333
走到这里了
当前异步任务4
当前异步任务2
*/
}
/**总结:
一、在同一串行队列种
同步里面创建同步 死锁崩溃
同步里面创建异步 正常
异步里面创建同步 死锁崩溃
异步里面创建异步 正常
二、在同一并发队列
同步里面创建同步 正常
同步里面创建异步 正常
异步里面创建同步 正常
异步里面创建异步 正常
*/
-(void)example71 {
//串行队列 同步里面创建同步 死锁崩溃
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example72 {
//串行队列 同步里面创建异步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example73 {
//串行队列 异步里面创建同步 死锁崩溃
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example74 {
//串行队列 异步里面创建异步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example81 {
//并发队列 同步里面创建同步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
sleep(1);
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example82 {
//并发队列 同步里面创建异步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
sleep(3);
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"走到这里了");
});
});
NSLog(@"结束");
}
-(void)example83 {
//并发队列 异步里面创建同步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
sleep(1);
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example84 {
//并发队列 异步里面创建异步 正常
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务1...");
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"任务2...");
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"走到这里了");
});
});
NSLog(@"结束");
}
-(void)example91{
//任务1和任务2在同一个线程里,在不同的队列里面,可以同步执行 运行正常
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue1, ^{
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"任务1...");
dispatch_sync(queue2, ^{
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"任务2...");
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example92{
//任务1和任务2在两个不同线程里,并且两个不同队列,不会造成死锁 可以正常运行
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue1, ^{
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"任务1...");
dispatch_async(queue2, ^{
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"任务2...");
});
NSLog(@"走到这里了");
});
NSLog(@"结束");
}
-(void)example10 {
//异步串行group
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[self doSomething:^() {
NSLog(@"任务一");
}];
});
dispatch_group_async(group, queue, ^{
[self doSomething:^() {
NSLog(@"任务二");
}];
});
dispatch_group_async(group, queue, ^{
[self doSomething:^() {
NSLog(@"任务三");
}];
});
dispatch_group_notify(group, queue, ^{
NSLog(@"前面的任务已完成");
});
}
-(void)example11 {
//异步串行group
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[self doSomething:^() {
NSLog(@"任务一");
}];
});
dispatch_group_async(group, queue, ^{
sleep(3);
[self doSomething:^() {
NSLog(@"任务二");
}];
});
dispatch_group_async(group, queue, ^{
[self doSomething:^() {
NSLog(@"任务三");
}];
});
dispatch_group_notify(group, queue, ^{
NSLog(@"前面的任务已完成");
});
}
- (void)doSomething:(void (^)(void))handler {
if (handler) {
sleep(2);
handler();
}
}
-(void)example12 {
// 因为 dispatch_group_async 里面的任务是异步的,所以任务在执行的时候,它不会去等待 for 循环执行结束,它会直接跳过 dispatch_async 这 block 执行下一句去了,所以 dispatch_group_notify 也会很快就执行。
// 创建一个group
dispatch_group_t group = dispatch_group_create();
// 创建一个队列:全局队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 将任务1添加到 group 中
dispatch_group_async(group, queue, ^{
// 模拟异步网络请求
sleep(5);
NSLog(@"任务一完成");
});
// 将任务2添加到 group 中
dispatch_group_async(group, queue, ^{
// 模拟异步网络请求
sleep(3);
NSLog(@"任务二完成");
});
// 任务1和任务2执行结束,回调
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"完成任务");
});
});
}
-(void)example13 {
// 创建一个group
dispatch_group_t group = dispatch_group_create();
// 创建一个队列:全局队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 进入group
dispatch_group_enter(group);
// 模拟异步网络请求
dispatch_async(queue, ^{
sleep(3);
// 离开group
NSLog(@"任务一完成");
dispatch_group_leave(group);
});
// 进入group
dispatch_group_enter(group);
// 模拟异步网络请求
dispatch_async(queue, ^{
sleep(4);
// 离开group
NSLog(@"任务二完成");
dispatch_group_leave(group);
});
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"完成任务");
});
});
}
-(void)example14{
// 创建一个group
dispatch_group_t group = dispatch_group_create();
// 创建一个队列:全局队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 创建信号量,并且设置值为0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// 将任务1添加到 group 中
dispatch_group_async(group, queue, ^{
// 模拟异步网络请求
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务一完成");
// 每次发送信号则 semaphore 会 +1
dispatch_semaphore_signal(semaphore);
});
// 由于是异步执行的,当 semaphore 等于 0,则会阻塞当前线程,直到执行了 block 的 dispatch_semaphore_signal,semaphore + 1,才会继续执行。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
// 将任务2添加到 group 中
dispatch_group_async(group, queue, ^{
// 模拟异步网络请求
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务二完成");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"完成任务");
});
});
}
@end
3.4.3.3.线程间的通信
- Direct messaging:这是大家非常熟悉的**-performSelector:系列**。
- Global variables…:直接通过全局变量、共享内存等方式,但这种方式会造成资源抢夺,涉及到线程安全问题。
- Conditions:一种特殊的锁–条件锁,当使用条件锁使一个线程等待(wait)时,该线程会被阻塞并进入休眠状态,在另一个线程中对同一个条件锁发送信号(single),则等待中的线程会被唤醒继续执行任务。
- Run loop sources:通过自定义Run loop sources来实现,后面的文章会单独研究Run loop。
- Ports and sockets:通过端口和套接字来实现线程间通讯。
- Run loop:NSMachPort
3.4.3.4.其他应用
1.延时执行
iOS常见三种延时执行方式
1)调用NSObject的方法
[self performSelector:@selector(需要执行的方法名) withObject:nil afterDelay:2.0]
2)使用GCD函数
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后执行这里的代码..
});
3)使用定时器
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(需要执行的方法名) userInfo:nil repeats:NO];
2.一次性代码
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//里面的代码只会被执行一次
});
3.队列组
有这么一个需求,首先:分别异步执行2个耗时的操作,其次:等2个异步操作都执行完毕后,再回到主线程执行操作,如果想要快速高效地实现上述需求,可以考虑用队列组。
dispatch_group_tgroup = dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});
4.快速迭代
我只想说速度非常快,要加一个__block因为block代码默认不能改外面的东西
5.barry执行任务函数
在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行。
下面的例子是在添加到队列的任务1、任务2、任务3执行完毕后,然后才执行barrier,barrier执行完毕后才执行任务4、任务5。
dispatch_barrier在并发队列中创建一个同步点,当并发队列中遇到一个 dispatch_barrier时,会延时执行该 dispatch_barrier,等待在 dispatch_barrier之前提交的任务block执行完后才开始执行,之后,并发队列继续执行后续block任务。
6.GCD与定时器
@property (nonatomic,strong) dispatch_source_t timer;
- (void) myTimer {
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
// 设置定时器的触发时间(1秒后)和时间间隔(每隔2秒)
dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), 2 * NSEC_PER_SEC, 0);
// 设置回调
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"Timer %@", [NSThread currentThread]);
});
// 开始定时器
dispatch_resume(self.timer);
}
-(void)viewDidDisappear:(BOOL)animated {
dispatch_cancel(self.timer);
self.timer = nil;
}