iOS 线程
1. pthread 1). 执行不带参数的方法 import <pthread/pthread.h> - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 创建子线程,线程编号 pthread_t pthread; // 第一个参数 线程编号的地址 // 第二个参数 线程的属性 // 第三个参数 线程的要执行的函数 // 第四个参数 要执行的函数的参数 // 返回值 int 0是成功 非0是失败 int result = pthread_create(&pthread, NULL, demo, NULL); NSLog(@"touchesBegan %@", [NSThread currentThread]); if (result) { NSLog(@"失败"); } else { NSLog(@"成功"); } } // 函数必须是C语言的 void *demo(void *param) { NSLog(@"hello %@", [NSThread currentThread]); return NULL; } 2). 执行带参数的方法 #import <pthread/pthread.h> - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 创建子线程, 线程编号 pthread_t pthread; char *nameC = "mazaiting"; int result = pthread_create(&pthread, NULL, demo, (void *)nameC); if (result) { NSLog(@"失败"); } else { NSLog(@"成功"); } NSString *nameNS = @"zaitingma"; // 传参时要将OC中的对象传递给C语言的函数,要使用桥接, __bridge int result1 = pthread_create(&pthread, NULL, demo1, (__bridge void *)nameNS); if (result1) { NSLog(@"失败"); } else { NSLog(@"成功"); } } // C函数, 传递OC对象 void *demo1(void *param) { NSString *string = (__bridge NSString *)param; NSLog(@"%@", string); return NULL; } // C函数, 传递C字符串 void *demo(void *param) { char *string = param; NSLog(@"%s", string); return NULL; } 2. NSThread 1). 创建线程 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self createThread]; } - (void)createThread { // 方式一 // 创建线程 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil]; // 开启线程 [thread start]; // 方式二 [NSThread detachNewThreadSelector:@selector(demo) toTarget:self withObject:nil]; // 方式三 [self performSelectorInBackground:@selector(demo) withObject:nil]; // 方式4 带参数 NSThread *threadParam = [[NSThread alloc] initWithTarget:self selector:@selector(demo1:) object:@"mazaiting"]; [threadParam start]; } - (void)demo1:(NSString *)name { NSLog(@"%@", name); } - (void)demo { // 打印当前线程 NSLog(@"hello %@", [NSThread currentThread]); } 2). 线程状态 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 新建状态 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil]; // 线程名 thread.name=@"t1"; // 线程的优先级 thread.threadPriority=1.0; // 就绪状态 [thread start]; } - (void)demo { for (int i = 0; i < 20; i++) { NSLog(@"%d", i); if (i == 5) { // 阻塞状态 -- 睡眠3秒 [NSThread sleepForTimeInterval:3]; } if (i == 10) { // 线程退出 -- 死亡状态 [NSThread exit]; } // 判断是否是主线程 if([NSThread isMainThread]){ continue; } } } 3). 线程互斥锁 - (void)demo1 { // 互斥锁 @synchronized(self) { NSLog(@"%@",self); } } 4). 自旋锁 @property (nonatomic, copy) NSString *name; // 为属性生成对应的成员变量 @synthesize name = _name; 5). 三种Block //2 block 为什么要用copy //第一种 block 全局block __NSGlobalBlock__ // void (^demo)() = ^{ // NSLog(@"aaa"); // }; // NSLog(@"%@",demo); //第二种block 栈Block __NSStackBlock__ // int number = 5; // void (^demo)() = ^{ // NSLog(@"aaa %d",number); // }; // NSLog(@"%@",demo); //第三种block 堆block __NSMallocBlock__ // int number = 5; // void (^demo)() = ^{ // NSLog(@"aaa %d",number); // }; // NSLog(@"%@",[demo copy]); 6). 子线程消息循环 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 开启一个子线程 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil]; [thread start]; // 往子线程的消息循环中添加输入源 [self performSelector:@selector(demo1) onThread:thread withObject:nil waitUntilDone:NO]; } // 执行在子线程上的方法 - (void)demo { NSLog(@"I am running!"); // 开启子线程的消息循环,如果开启,消息循环一直运行 // 当子线程循环中没有添加输入事件,消息循环会立即结束 // [[NSRunLoop currentRunLoop] run]; // 2秒钟后消息循环结束 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; NSLog(@"end"); } // 执行在子线程的消息循环中 - (void)demo1 { NSLog(@"I'm running on runloop!"); } @end 3. GCD 1). 简单使用 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 1. 创建队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2. 创建任务 dispatch_block_t task = ^ { NSLog(@"hello %@",[NSThread currentThread]); }; // 3. 异步执行 dispatch_async(queue, task); // 简化用法 dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"mazaiting %@", [NSThread currentThread]); // 回到主线程 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"----%@", [NSThread mainThread]); }); }); } @end 2). 串行队列 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self sync]; [self async]; } // 串行队列,同步执行 不开新线程,任务是顺序执行的 - (void)sync { dispatch_queue_t queue = dispatch_queue_create("mazaiting", DISPATCH_QUEUE_SERIAL); for (int i = 0; i < 10; i++) { dispatch_sync(queue, ^{ NSLog(@"%d---%@", i, [NSThread currentThread]); }); } } // 串行队列,异步执行 开新线程(1个),任务是有序执行的 - (void)async { dispatch_queue_t queue = dispatch_queue_create("mazaiting", DISPATCH_QUEUE_SERIAL); for (int i = 0; i < 10; i++) { dispatch_async(queue, ^{ NSLog(@"%d---%@", i, [NSThread currentThread]); }); } } @end 3). 并行队列 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self sync]; [self async]; } // 并行队列,同步执行 --- 串行队列,同步执行,不开线程,顺序执行 - (void)sync { dispatch_queue_t queue = dispatch_queue_create("mazaiting", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i++) { dispatch_sync(queue, ^{ NSLog(@"%d---%@", i, [NSThread currentThread]); }); } } // 并行队列,异步执行 --- 开多个线程,无序执行 - (void)async { dispatch_queue_t queue = dispatch_queue_create("mazaiting", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i++) { dispatch_async(queue, ^{ NSLog(@"%d---%@", i, [NSThread currentThread]); }); } } @end 4). 主队列 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // [self demo]; // [self demo1]; [self demo2]; } // 1. 主队列,异步执行 --- 主线程,顺序执行 // 主队列特点:先执行完主线程上的代码,才会执行主队列中的任务 - (void)demo { for (int i = 0; i < 10; i++) { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"hello %d %@", i, [NSThread currentThread]); }); } } // 2. 主队列,同步执行 --- 主线程上执行才会死锁 // 同步执行: 会等着第一个任务执行完成后才会继续往后执行 - (void)demo1 { NSLog(@"开始"); for (int i = 0; i < 10; i++) { // 死锁 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"hello %d %@", i, [NSThread currentThread]); }); } NSLog(@"结束"); } // 3. 解决死锁 - (void)demo2 { NSLog(@"开始"); dispatch_async(dispatch_get_global_queue(0, 0), ^{ for (int i = 0; i < 10; i++) { // 死锁 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"hello %d %@", i, [NSThread currentThread]); }); } }); NSLog(@"结束"); } @end 5). 延迟执行和一次性执行 //1 延迟执行 // dispatch_time_t when, 延迟多长时间 精度到纳秒 // dispatch_queue_t queue, 队列 // dispatch_block_t block 任务 // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // // NSLog(@"task"); // }); //2 一次性执行 // for (int i = 0; i<20000; i++) { // static dispatch_once_t onceToken; // dispatch_once(&onceToken, ^{ // NSLog(@"hello %@",[NSThread currentThread]); // }); // } 6). 调度组 @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } //下载三首歌曲,当歌曲都下载完毕 通知用户 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self demo2]; } //调度组内部的原理 - (void)demo2 { //创建组 dispatch_group_t group = dispatch_group_create(); //创建队列 dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT); //任务1 dispatch_group_enter(group); dispatch_async(queue, ^{ NSLog(@"任务1"); dispatch_group_leave(group); }); //任务2 dispatch_group_enter(group); dispatch_async(queue, ^{ NSLog(@"任务2"); dispatch_group_leave(group); }); //任务3 dispatch_group_enter(group); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2.0]; NSLog(@"任务3"); dispatch_group_leave(group); }); //等待组中的任务都执行完毕,才会执行 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"over"); }); //等待组中的任务都执行完毕,才会继续执行后续的代码 dispatch_group_wait(group, DISPATCH_TIME_FOREVER); NSLog(@"hello "); } //演示调度组的基本使用 - (void)demo1 { //创建组 dispatch_group_t group = dispatch_group_create(); //队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //下载第一首歌曲 dispatch_group_async(group, queue, ^{ NSLog(@"正在下载第一个歌曲"); }); //下载第二首歌曲 dispatch_group_async(group, queue, ^{ NSLog(@"正在下载第二个歌曲"); [NSThread sleepForTimeInterval:2.0]; }); //下载第三首歌曲 dispatch_group_async(group, queue, ^{ NSLog(@"正在下载第三个歌曲"); }); //当三个异步任务都执行完成,才执行 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"over %@",[NSThread currentThread]); }); } @end 4. NSOperation 1). 创建 @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 1. 调用start执行, 不会开启新线程,start方法更新操作的状态,调用main方法 // 创建 NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil]; NSLog(@"--%d", op.isFinished); // 开始执行 [op start]; NSLog(@"--%d", op.isFinished); // 2. 添加到队列 // 创建操作 NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil]; // 添加到队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 将操作添加到队列 [queue addOperation:op1]; } - (void)demo { NSLog(@"hello %@", [NSThread currentThread]); } @end 2). BlockOperation #import "ViewController.h" @interface ViewController () //全局队列 @property (nonatomic, strong) NSOperationQueue *queue; @end @implementation ViewController //懒加载 - (NSOperationQueue *)queue { if (_queue == nil) { _queue = [[NSOperationQueue alloc] init]; } return _queue; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self demo5]; } //演示start - (void)demo1 { //创建操作 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"hello %@",[NSThread currentThread]); }]; //更新op的状态,执行main方法 [op start]; //不会开新线程 } //把操作添加到队列 - (void)demo2 { //创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //创建操作 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"hello %@",[NSThread currentThread]); }]; //把操作添加到队列中 [queue addOperation:op]; } - (void)demo3 { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ NSLog(@"hello %@",[NSThread currentThread]); }]; } //全局队列 - (void)demo4 { // //并发队列,异步执行 // for (int i = 0; i < 10; i++) { // [self.queue addOperationWithBlock:^{ // NSLog(@"hello %d %@",i,[NSThread currentThread]); // }]; // } } // 操作的 completionBlock - (void)demo5 { NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:2]; NSLog(@"hello %@",[NSThread currentThread]); }]; //操作完成之后执行 [op setCompletionBlock:^{ NSLog(@"end %@",[NSThread currentThread]); }]; [self.queue addOperation:op]; } @end 3). 线程间通信 #import "ViewController.h" @interface ViewController () //全局队列 @property (nonatomic, strong) NSOperationQueue *queue; @end @implementation ViewController //懒加载 - (NSOperationQueue *)queue { if (_queue == nil) { _queue = [[NSOperationQueue alloc] init]; } return _queue; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self.queue addOperationWithBlock:^{ //异步下载图片 NSLog(@"异步下载图片"); //获取当前队列 // [NSOperationQueue currentQueue] //线程间通信,回到主线程更新UI [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"更新UI"); }]; }]; } @end 4). 操作的依赖 #import "ViewController.h" @interface ViewController () @property (nonatomic, strong) NSOperationQueue *queue; @end @implementation ViewController - (NSOperationQueue *)queue { if (_queue == nil) { _queue = [NSOperationQueue new]; } return _queue; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 下载 - 解压 - 升级完成 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载"); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:2.0]; NSLog(@"解压"); }]; //设置优先级最高 op2.qualityOfService = NSQualityOfServiceUserInteractive; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"升级完成"); }]; //设置操作间的依赖 [op2 addDependency:op1]; [op3 addDependency:op2]; //错误,会发生循环依赖,什么都不执行 // [op1 addDependency:op3]; //操作添加到队列中 [self.queue addOperations:@[op1,op2] waitUntilFinished:NO]; //依赖关系可以夸队列执行 [[NSOperationQueue mainQueue] addOperation:op3]; } @end 5). 自定义操作 步骤: 继承NSOperation类,并重写main方法 CustomOperation.h #import <Foundation/Foundation.h> @interface CustomOperation : NSOperation @end CustomOperation.m #import "CustomOperation.h" @implementation CustomOperation - (void)main { NSLog(@"mazaiting"); } @end ViewController.m #import "ViewController.h" #import "CustomOperation.h" @interface ViewController () @end @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { CustomOperation *co = [[CustomOperation alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:co]; } @end