在分析问题之前,我们先区分两个概念:进程和线程 了解以上之后,我们来定义一个方法 求0-63000000的和 -(void)test{ NSLog(@"%@,%d",[NSThread currentThread],[[NSThread mainThread]isMainThread]); @autoreleasepool { long int sum = 0; long int num = 63550000; for (long int i = 1; i <= num; i++) { sum +=i; } NSLog(@"%ld",sum); } 调用以上方法我们发现返回计算结果的时间我们还能接受 但是在63000000后面加上一个或者更多0 再次试一次 就会发现 这个时间计算机的计算速度非常慢,这时候我们就可以考虑开辟多条线程来加快程序运行效率。 二、开辟多线程有哪些方式?1、在后台执行 开辟多线程最简单的一个方法 [self performSelectorInBackground:@selector(test) withObject:nil];
2、NSThread /* 第一种*/ //1 由init来创建并且需要手动来开启 NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil]; //2 开启线程 [thread start]; //3 取消线程 [thread cancel];//这个很少有人在用 一般也不会写在这个地方 /* 第二种 */ //初始化的时候自动开启线程 [NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
3、NSOperation NSInvocationOperation *incocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil]; __weak typeof(self)temp = self; NSBlockOperation *block =[NSBlockOperation blockOperationWithBlock:^{ [temp test]; NSLog(@"这个是BlockOprationQueue执行的"); }]; //NSOperationQueue是线程操作队列 用来管理一组Operation对象 会根据实际需求创建出合适数量的子线程 完成任务的并发执行 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //当最大并发执行数为1的时候程序是串行执行的 [queue setMaxConcurrentOperationCount:1]; //设置依赖关系[A addDependency B]若A依赖B则B先执行A在执行 若B依赖A则A先执行B在执行 [invocation addDependency:blockOperation]; #pragma mark ---上面两部要写在添加之前--- [queue addOperation:invocation]; [queue addOperation:blockOperation]; 我们运行一下程序结果:
4、GCD dispatch_queue_t queue = dispatch_get_main_queue(); // 网队列里面添加任务 dispatch_async(queue, ^{ [temp test]; NSLog(@"1"); }); dispatch_async(queue, ^{ [temp test]; NSLog(@"2"); }); dispatch_async(queue, ^{ [temp test]; NSLog(@"3"); }); 结果显示:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"今晚在如家402一起敲代码,好么?"); }); (2)全局队列 并发执行 dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(global, ^{ [temp test]; NSLog(@"11"); }); dispatch_async(global, ^{ [temp test]; NSLog(@"22"); }); dispatch_async(global, ^{ [temp test];NSLog(@"33"); });
dispatch_apply(5, global, ^(size_t t) {//相当于int t NSLog(@"执行到第%ld次",t); }); (3)自定义队列 //串行队列 dispatch_queue_t queue = dispatch_queue_create("AAA", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ [temp test]; NSLog(@"111"); }); dispatch_async(queue, ^{ [temp test]; NSLog(@"222"); }); dispatch_async(queue, ^{ [temp test]; NSLog(@"333"); }); //分组任务 返回结果的先后顺序就不是确定的了 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ [temp test]; NSLog(@"1111"); }); dispatch_group_async(group, queue, ^{ [temp test]; NSLog(@"2222"); }); dispatch_group_async(group, queue, ^{ [temp test]; NSLog(@"3333"); }); //这句话就是一个谦虚的狗做的 拒绝拿第一 dispatch_group_notify(group, queue, ^{ NSLog(@"昭哥变成了数学家"); }); //障碍执行 执行任务的时候 要是前面还有任务的话就会等其他任务执行完之后在再执行 该方法创建的任务在执行的时候 会先检查是不是有其他任务正在执行 要是有等待其执行完毕 再进行执行 否则其他任务要等待其执行完毕之后再执行 dispatch_barrier_sync(queue, ^{ [temp test]; NSLog(@"这个叫做障碍执行"); }); //不争不抢 最后一步执行 dispatch_group_notify(queue3, queue2, ^{ NSLog(@"昭哥变成了数学家"); }); 三、子线程回到主线程简单介绍几种常用子线程回到主线程的方式 // GCD dispatch_async(dispatch_get_main_queue(), ^{ //在这里面进行主线程任务的操作(UI的刷新) }); // NSObject // (1) [self performSelectorOnMainThread:@selector(backMainThread) withObject:nil waitUntilDone:YES]; // (2) [self performSelector:@selector(backMainThread) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES]; 4、模拟购票系统
声明一个全局变量 int count = 10000; 假设10000张票 __weak typeof(self)temp = self; dispatch_queue_t queue3 = dispatch_queue_create("CCC", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue3, ^{ for (int i = 0; i < 100; i++) { [temp buyTickets]; } }); dispatch_async(queue3, ^{ for (int i = 0; i < 100; i++) { [temp buyTickets]; } }) 防止发生购票冲突 我们使用了互斥锁 -(void)buyTickets{ //线程互斥 @autoreleasepool { [_lock lock]; count--; NSLog(@"剩余票数%d",count); [_lock unlock]; } }(责任编辑:最模板) |