iOS开发 多线程和GCD
2016-01-08 10:43
441 查看
多线程
多线程的三种方式:1.thread 2.OPerationQuete 3.NSObject
多线程:程序:有源代码生成可执行应用(.exe,.app)
进程:一个正在运行的程序可以看做是一个进程,进程拥有独立运行所需的全部资源
线程:多线程是为了系统可以运行多个程序,多线程是为了app可以运行多个任务
进程拥有独立的资源,线程不会
一个程序有一个或多个线程组成,进程只负责资源的调度,线程才是程序真正执行单元,负责代码执行
一个程序至少有一个线程,称为主线程,程序中只有一个主线程的程序,叫单线程程序;运行中会有多个线程的程序,叫多线程程序
子线程:iOS中允许用户开辟新线程,相对于主线程来说这些都是子线程
主线程:负责界面展现和刷新,旧版网络请求,数据库的请求,这些代码只能顺序执行,不能并发执行,
多线程的原理:CPU只能处理一条线程,只有一个线程在工作执行,多线程并发同时执行,其实就是CPU在多条线程之间调度切换,如果CPU调度线程的时间足够快,就造成多条线程并发执行的假象
思考:如果线程非常非常多,会发生什么情况?
CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源
每条线程被调度执行的频次会降低(线程的执行效率降低)
3.多线程的优缺点
多线程的优点
能适当提高程序的执行效率
能适当提高资源利用率(CPU、内存利用率)
多线程的缺点
开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,CPU在调度线程上的开销就越大
程序设计更加复杂:比如线程之间的通信、多线程的数据共享
4.多线程在iOS开发中的应用
主线程:一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的主要作用
1. 显示\刷新UI界面
2. 处理UI事件(比如点击事件、滚动事件、拖拽事件等)
3.主线程的使用注意:别将比较耗时的操作放到主线程中。
4. 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
在storyboard中添加一个按钮,再拖拽点击事件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark thread方式;
- (IBAction)CountAction:(id)sender {
/*
//开启多线程
//方式一:需要手动在合适时机开启线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction) object:nil];
thread.name = @"text";
//手动开启;
[thread start];
//方式二:直接就开启线程,不需要手动启动
//[NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:nil];
NSLog(@"%@",[NSThread currentThread]);
*/
#pragma mark NSOperationQueue;
/*
NSOperationQueue:操作队列
会根据操作的数量分配合适的线程去进行操作,通常与NSOperation进行配合操作,用户可以不用关心多线程,只需将每个多线程的任务做成NSOperation,然后放到队列中。队列会自动创建合适的线程
NSOperation:操作
NSOperation:本身并没有子线程,只是一个操作,多线程的是Queue
NSOperation:是一个抽象类,不能直接使用,一般是使用他的子类NSBlockOperation,NSInvocationOperation
*/
/*
//创建操作
NSInvocationOperation *op1 =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil];
//
//[op1 start];
//创建操作
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block:%@",[NSThread currentThread]);
// [op2 start];
} ];
// NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"block2:%@",[NSThread currentThread]);
// }];
//
// NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"block3:%@",[NSThread currentThread]);
// }];
//
//创建操作队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//每个操作可以设置优先级
op1.queuePriority = NSOperationQueuePriorityHigh;
//queue可以设置最大并行线程数
//当最大线程数设置为1的时候,是串行(可以保证任务是串行的)但是不能保证线程好使一样的
queue.maxConcurrentOperationCount = 3;
[op1 addDependency:op2];//添加依赖,当第二个执行结束的时候
[queue addOperation:op1];
[queue addOperation:op2];
// [queue addOperation:op3];
// [queue addOperation:op4];
*/
#pragma mark NSObject
[self performSelectorInBackground:@selector(threadAction) withObject:nil];
NSLog(@"%@",[NSThread currentThread]);
}
//NSOperationQueue;的点击事件
- (void)invocationAction{
NSLog(@"invocation:%@",[NSThread currentThread]);
}
- (void)threadAction{
//输出1-1000000
for (int i = 0; i < 1000000; i++) {
// NSLog(@"%d",i);
}
NSLog(@"%@",[NSThread currentThread]);
}
@end
GCD
全称:Grand Central Dispatch :是苹果公司开发的,以优化应用程序支持多核和其他对称多系统的系统
GCD是函数级编程,所以更高效,功能更强大
任务:
具有一定功能的代码段,一般是一个Block或者函数
分发队列:
GCD以队列的方式进行工作,FIFO(先进先出)。
GCD会根据分发队列的不同,创建合适数量的线程执行队列中的任务
队列两种:
一种是串行队列:1.系统提供的串行队列 2.自定义串行队列
一种是并行队列:1.系统提供的串行队列 2.自定义串行队列
在storyboard中建立几个button,并拖拽点击事件
//采用系统方式添加串行任务
- (IBAction)SerialMainAction:(id)sender {
//系统提供的串行队列其实就是主线程队列
//1.拿到主线程队列
dispatch_queue_t main = dispatch_get_main_queue();
//2.给主线程队列添加任务
dispatch_async(main, ^{
NSLog(@"我是主线程队列第1个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第2个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第3个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第4个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第5个任务%@",[NSThread currentThread]);
});
}
//采用自定义的方式添加串行任务
- (IBAction)SerialBySelfAction:(id)sender {
//创建串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("yan5", DISPATCH_QUEUE_SERIAL);
//添加任务
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第一个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第二个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第三个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第四个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第五个%@",[NSThread currentThread]);
});
}
//通过系统方式创建并行队列
- (IBAction)GlobalAction:(id)sender {
//拿到并行队列
dispatch_queue_t globle = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//添加任务
dispatch_async(globle, ^{
NSLog(@"系统并行的第一个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第二个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第三个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第四个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第五个任务:%@",[NSThread currentThread]);
});
}
//自定义方式创建并行队列
- (IBAction)ConcurrentAction:(id)sender {
//拿到并行队列
dispatch_queue_t concurrent = dispatch_queue_create("1146", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第一个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第二个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第三个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第四个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第五个任务:%@",[NSThread currentThread]);
});
}
//让任务延迟一段时间执行
- (IBAction)DelayAction:(id)sender {
double time = 6;
//第一个参数从什么时候开始延迟
//第二个参数延迟多长时间
dispatch_time_t DTime = dispatch_time(DISPATCH_TIME_NOW, time * NSEC_PER_SEC);
//拿到队列
dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//拿到全局队列
//添加延时任务
dispatch_after(DTime, global, ^{
NSLog(@"我被执行");
});
}
//重复执行一个任务
//重复执行任务只能跟串行一起用
- (IBAction)RepeatAction:(id)sender {
//拿到全局队列
dispatch_queue_t globel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSArray *arr = @[@"阿猫",@"阿狗",@"阿彪"];
//添加重复任务
//1参数重复多少次2参数放在哪一个队列里 3参数任务的Block块
dispatch_apply(arr.count, globel, ^(size_t size) {
NSLog(@"arr[%zu]:%@",size,arr[size]);
});
}
// 让线程在程序运行期间只运行一次
- (IBAction)OnlyYouAction:(id)sender {
//创建一个静态的进程
static dispatch_once_t once;
dispatch_once(&once, ^{
NSLog(@"一次就好");
});
}
//线程之间的通信
/*
1.子线程中使用主线程的数据
2.主线程中使用子线程的数据
*/
多线程的三种方式:1.thread 2.OPerationQuete 3.NSObject
多线程:程序:有源代码生成可执行应用(.exe,.app)
进程:一个正在运行的程序可以看做是一个进程,进程拥有独立运行所需的全部资源
线程:多线程是为了系统可以运行多个程序,多线程是为了app可以运行多个任务
进程拥有独立的资源,线程不会
一个程序有一个或多个线程组成,进程只负责资源的调度,线程才是程序真正执行单元,负责代码执行
一个程序至少有一个线程,称为主线程,程序中只有一个主线程的程序,叫单线程程序;运行中会有多个线程的程序,叫多线程程序
子线程:iOS中允许用户开辟新线程,相对于主线程来说这些都是子线程
主线程:负责界面展现和刷新,旧版网络请求,数据库的请求,这些代码只能顺序执行,不能并发执行,
多线程的原理:CPU只能处理一条线程,只有一个线程在工作执行,多线程并发同时执行,其实就是CPU在多条线程之间调度切换,如果CPU调度线程的时间足够快,就造成多条线程并发执行的假象
思考:如果线程非常非常多,会发生什么情况?
CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源
每条线程被调度执行的频次会降低(线程的执行效率降低)
3.多线程的优缺点
多线程的优点
能适当提高程序的执行效率
能适当提高资源利用率(CPU、内存利用率)
多线程的缺点
开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,CPU在调度线程上的开销就越大
程序设计更加复杂:比如线程之间的通信、多线程的数据共享
4.多线程在iOS开发中的应用
主线程:一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的主要作用
1. 显示\刷新UI界面
2. 处理UI事件(比如点击事件、滚动事件、拖拽事件等)
3.主线程的使用注意:别将比较耗时的操作放到主线程中。
4. 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
在storyboard中添加一个按钮,再拖拽点击事件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark thread方式;
- (IBAction)CountAction:(id)sender {
/*
//开启多线程
//方式一:需要手动在合适时机开启线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction) object:nil];
thread.name = @"text";
//手动开启;
[thread start];
//方式二:直接就开启线程,不需要手动启动
//[NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:nil];
NSLog(@"%@",[NSThread currentThread]);
*/
#pragma mark NSOperationQueue;
/*
NSOperationQueue:操作队列
会根据操作的数量分配合适的线程去进行操作,通常与NSOperation进行配合操作,用户可以不用关心多线程,只需将每个多线程的任务做成NSOperation,然后放到队列中。队列会自动创建合适的线程
NSOperation:操作
NSOperation:本身并没有子线程,只是一个操作,多线程的是Queue
NSOperation:是一个抽象类,不能直接使用,一般是使用他的子类NSBlockOperation,NSInvocationOperation
*/
/*
//创建操作
NSInvocationOperation *op1 =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil];
//
//[op1 start];
//创建操作
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block:%@",[NSThread currentThread]);
// [op2 start];
} ];
// NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"block2:%@",[NSThread currentThread]);
// }];
//
// NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"block3:%@",[NSThread currentThread]);
// }];
//
//创建操作队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//每个操作可以设置优先级
op1.queuePriority = NSOperationQueuePriorityHigh;
//queue可以设置最大并行线程数
//当最大线程数设置为1的时候,是串行(可以保证任务是串行的)但是不能保证线程好使一样的
queue.maxConcurrentOperationCount = 3;
[op1 addDependency:op2];//添加依赖,当第二个执行结束的时候
[queue addOperation:op1];
[queue addOperation:op2];
// [queue addOperation:op3];
// [queue addOperation:op4];
*/
#pragma mark NSObject
[self performSelectorInBackground:@selector(threadAction) withObject:nil];
NSLog(@"%@",[NSThread currentThread]);
}
//NSOperationQueue;的点击事件
- (void)invocationAction{
NSLog(@"invocation:%@",[NSThread currentThread]);
}
- (void)threadAction{
//输出1-1000000
for (int i = 0; i < 1000000; i++) {
// NSLog(@"%d",i);
}
NSLog(@"%@",[NSThread currentThread]);
}
@end
GCD
全称:Grand Central Dispatch :是苹果公司开发的,以优化应用程序支持多核和其他对称多系统的系统
GCD是函数级编程,所以更高效,功能更强大
任务:
具有一定功能的代码段,一般是一个Block或者函数
分发队列:
GCD以队列的方式进行工作,FIFO(先进先出)。
GCD会根据分发队列的不同,创建合适数量的线程执行队列中的任务
队列两种:
一种是串行队列:1.系统提供的串行队列 2.自定义串行队列
一种是并行队列:1.系统提供的串行队列 2.自定义串行队列
在storyboard中建立几个button,并拖拽点击事件
//采用系统方式添加串行任务
- (IBAction)SerialMainAction:(id)sender {
//系统提供的串行队列其实就是主线程队列
//1.拿到主线程队列
dispatch_queue_t main = dispatch_get_main_queue();
//2.给主线程队列添加任务
dispatch_async(main, ^{
NSLog(@"我是主线程队列第1个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第2个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第3个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第4个任务%@",[NSThread currentThread]);
});
dispatch_async(main, ^{
NSLog(@"我是主线程队列第5个任务%@",[NSThread currentThread]);
});
}
//采用自定义的方式添加串行任务
- (IBAction)SerialBySelfAction:(id)sender {
//创建串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("yan5", DISPATCH_QUEUE_SERIAL);
//添加任务
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第一个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第二个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第三个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第四个%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"自定义串行任务第五个%@",[NSThread currentThread]);
});
}
//通过系统方式创建并行队列
- (IBAction)GlobalAction:(id)sender {
//拿到并行队列
dispatch_queue_t globle = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//添加任务
dispatch_async(globle, ^{
NSLog(@"系统并行的第一个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第二个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第三个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第四个任务:%@",[NSThread currentThread]);
});
dispatch_async(globle, ^{
NSLog(@"系统并行的第五个任务:%@",[NSThread currentThread]);
});
}
//自定义方式创建并行队列
- (IBAction)ConcurrentAction:(id)sender {
//拿到并行队列
dispatch_queue_t concurrent = dispatch_queue_create("1146", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第一个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第二个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第三个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第四个任务:%@",[NSThread currentThread]);
});
dispatch_async(concurrent, ^{
NSLog(@"自定义并行队列第五个任务:%@",[NSThread currentThread]);
});
}
//让任务延迟一段时间执行
- (IBAction)DelayAction:(id)sender {
double time = 6;
//第一个参数从什么时候开始延迟
//第二个参数延迟多长时间
dispatch_time_t DTime = dispatch_time(DISPATCH_TIME_NOW, time * NSEC_PER_SEC);
//拿到队列
dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//拿到全局队列
//添加延时任务
dispatch_after(DTime, global, ^{
NSLog(@"我被执行");
});
}
//重复执行一个任务
//重复执行任务只能跟串行一起用
- (IBAction)RepeatAction:(id)sender {
//拿到全局队列
dispatch_queue_t globel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSArray *arr = @[@"阿猫",@"阿狗",@"阿彪"];
//添加重复任务
//1参数重复多少次2参数放在哪一个队列里 3参数任务的Block块
dispatch_apply(arr.count, globel, ^(size_t size) {
NSLog(@"arr[%zu]:%@",size,arr[size]);
});
}
// 让线程在程序运行期间只运行一次
- (IBAction)OnlyYouAction:(id)sender {
//创建一个静态的进程
static dispatch_once_t once;
dispatch_once(&once, ^{
NSLog(@"一次就好");
});
}
//线程之间的通信
/*
1.子线程中使用主线程的数据
2.主线程中使用子线程的数据
*/
相关文章推荐
- iOS MKMapView Error Domain=kCLErrorDomain Code=0 “(null)” Simulator
- iOS系统语音播报文字
- iOS开发过程中一些数据的存储归档
- iOS-hitTest:withEvent与自定义hit-testing规则
- iOS 打印日志显示系统详细时间,类名,行号及打印值
- ARC 完全指南
- iOS NSNotificationCenter详解
- ios9 简单粗暴总结
- iOS图片拉伸技巧—— resizableImageWithCapInsets
- iOS监听键盘弹出
- iOS使用NSUserDefaults保存用户名和密码
- ios non-arc to arc 之三
- iOS cell排序
- 学习笔记5: 仿ios Dialog
- xcode7、iOS9 设置启动图片(Launch Image)
- IOS 去空格处理 特殊字符处理
- ios 非arc转arc 之二
- IOS笔记
- iOS开发调试技巧总结(持续更新中)
- iOS倒计时的实现